——每天的寥寥几笔,坚持下去,将会是一份沉甸甸的积累。
今天的笔记是有关核心一的接口部分(作为个人笔记,就仅把我认为重要的记录了下来,一些较基础的就跳过不写了)。
1.实例域与类域的概念。实例域就是要new出来对象后对象所拥有的数据域,而类域则是类所有,编译时就已经属于类了。
接口不能含有实例域,也不能实现方法,仅能含有static final的数据域和未实现的public方法。
2.clone之深浅复制
所谓浅复制,就是说复制完的那个对象和原对象拥有一样的引用,一个对象的数据段变了,另一个跟着一起变。
Person a = new Person("wangwu"); Person copy = a; copy.setName("zhangsan");//此时a.getName="zhangsan"
所谓深复制,就是复制完两个对象各归各的,数据互不影响。
为此,设计者还为我们提供了一个接口cloneable。只要implements该接口,并恰当的覆写从Object那里继承来的clone方法,就能通过调用clone方法实现深复制。这里要强调下,clone方法是覆写父类Object的方法,而不是实现接口的方法,因为cloneable接口里面并没有clone方法,这里implements这个接口仅仅是为了做个标记,表明类设计者要进行克隆处理。
上面我着重加粗了“恰当的覆写“,因为这里有陷阱,必须要小心。
首先明确,什么是复制拷贝。就是将一个对象中的所有数据都复制另一个对象中,同时要满足深复制。这里就会有两种情况:
一:如果对象中的数据域都是数值或基本数据类型,这样的拷贝不会出错。
二:如果对象中的数据域含有对象的引用(包含String类型),那么要小心了,拷贝的结果会使复制出来的对象和原对象中的对象引用都会指向同一个区域,也就违背了深复制的原则。所以,需要单独拿出来处理。
public Person clone(){ if(null == this) return null; Person person = super.clone();//默认方法只对数值和基本数据类型起作用 person.name = "wagnwu".clone();//对于对象引用,克隆出一份,然后再自己手动设置成clone出的结果即可 person.birthday = (Date)birthday.clone(); return person; }
3.内部类之局部、匿名、静态内部类
内部类:定义在类中的类。
最重要的一个需要理解的点:
1.编译时,内部类会被特殊对待,假设类A中有一内部类B,那么编译完成会生成一个A.class和一个A$B.class(内部类专属字节码),可以看出,结果都是class文件,因此,虚拟机完全不用管该class文件是内部类还是外部类,按照自己的规则处理class文件即可,这样的设计方法是低耦合的,高效的。
2.不过,编译完生成A$B的class文件会被添加一个构造函数,参数就是外部类的this引用,这样的话,内部类就可以通过this对象直接对外部类的数据进行操作,实现了两个类之间的交互。后面提到的静态内部类,就是把this给抛掉了,因为人家没想着要访问外部类的数据。
****后加的两点,比较重要,不要忽视******
3.而外部类A.class还会生成多个静态方法,返回值为外部类的实例域,而方法参数为外部类实例对象,这样内部类就能调用这个静态方法,通过该方法的返回值直接访问外部类的私有数据,而不用通过公有的getter方法。
4.局部内部类不能用public,private访问说明符修饰,因为它的作用域限定在了声明这个类的局部块中。
局部内部类:
1.定义在方法体或代码块中
2.对外部世界完全隐藏,同时也能访问外部类,并且,还能访问final类型的局部变量,因为编译阶段会在该局部类中生成相关构造函数和对应局部变量的拷贝,该构造函数可以给该拷贝变量赋值。
public void start(boolean beep){ class TimePrinter implements Actionlistener{ public void actionPerformed(ActionEvent event){ if(beep) dosomething //局部变量beep可以被内部类保存 } } Actionlistener listener = new TimePrinter(); }
class TalkingClock$TimePrinter{ TalkingClock$TimePrinter(TalkingClock,boolean); public void actionPerformed(java.awt.actionEvent); final boolean val$beep;//beep是外部类的局部变量 final TalkingClock this$0;//外部类引用 }
匿名内部类:
Person p1 = new Person("ace");//a person object
Person p2 = new Person("ace"){//an object of inner class //data or methods }
拓展技巧:双括号初始化
ArrayList<String> f = new ArrayList<String>(); f.add("a"); f.add("b"); invite(f); //两种方式是等价的,但下面的方法更简洁,因为使用了匿名列表 invite(new ArrayList<String>(){ { add("a"); add("b"); } });
静态内部类:
当仅仅为了隐藏某一内部类,同时内部类也不需要访问外部类(用不到外部类的this对象)时,可以将内部类声明成静态的,这样可以实现完全的隐藏。
我cao,又这么晚了。学生党够拼,也该睡了。。后面再完善吧。