概述:
- 接口技术,主要用来描述类具有什么功能,而并不给出每个功能的具体实现。一个类可以实现一个或多个接口,并在需要接口的地方,随时使用实现了相应接口的对象。
- 克隆对象(深拷贝),指创建一个新对象,且新对象的状态与原始对象的状态相同。当对克隆的新对象进行修改时,不会影响原始对象的状态。
- 内部类,内部类定义在另一个类的内部,内部类中的方法可以访问包含它们的外部类的域。内部类技术主要用于设计具有相互协作关系的类集合。
- 代理,这是一种实现任意接口的对象。代理是一种非常专业的构造工具,它可以用来构建系统级的工具。
(1)接口
- 在Java语言中,接口不是类,而是对类的一组需求描述,这些类要遵从接口描述的统一格式进行定义。
- 接口中所有方法都自动地属于 public。因此,在接口中声明方法时,不必提供关键字 public。
- 接口绝不能含有实例域,也不能在接口中实现方法(接口可以看成是没有实例域的抽象类,但是二者还是有一定的区别)。
- 实现接口的两个步骤:
- 将类声明为实现给定的接口;
- 对接口中的所有方法进行定义。
注意:在实现接口时,必须把方法声明为public;否则,编译器将认为这个方法的访问属性是包可见的,即类的默认访问属性,之后编译器就会给出试图提供更弱的访问权限的警告信息。
问题:为什么不能在 Employee 类直接提供一个 compareTo 方法,而必须实现 Comparable 接口呢?
①接口的特性
不能使用 new 实例化接口,但可以声明接口变量:
Comparable x = new Employee(...); //Employee implements Comparable
可以使用 instanceof 方法检查一个对象是否实现了某个特定接口:
if(anObject instanceof Comparable){...}
与类被继承一样,接口也可以被扩展。这里允许存在多条从具有较高通用性的接口到较高专用性的接口的链。
- 接口中不能包含实例域或静态方法,但却可以包含常量域(默认为 public static final) 。
- 一个类只能拥有一个父类,但却可以实现多个接口。这就为定义类的行为提供了极大的灵活性。
②接口与抽象类
在已经由抽象类后,为什么Java语言还引入接口概念?
class Employee extends Person, Comparable //ERROR
class Employee extends Person implements Comparable //OK
因为,抽象类表示通用属性存在这样的一个问题:每个类只能扩展一个类。如上例,每个类可以实现多个接口(接口间用逗号隔开)。
C++实现了类的多继承,为什么Java不采用这种方式?
原因:多继承会让语言本身变得更复杂(如C++),且效率也会降低。
实际上,接口可以提供多继承的大多数好处,同时还能避免多重继承的复杂性和低效率。
(2)对象克隆
拷贝与克隆的区别:
拷贝一个变量时,原始元素与拷贝元素引用同一个对象。就是说,改变一个变量所引用的对象将会对另一个变量产生影响。
克隆(深拷贝),改变一个变量时,另一个变量不会受到影响。
浅拷贝:Object中的clone方法,默认是将对象中的各个域进行对应的拷贝。如果对象中所有数据域都属于数值或基本类型,这样拷贝域没有任何问题。但是,如果在对象中包含了子对象的引用,拷贝的结果会使得两个域引用同一个子对象,因此原始对象与克隆对象共享这部分信息。
深拷贝:将对象中的子对象也进行拷贝。
浅拷贝存在的问题:
视情况而定。如果原始对象和浅拷贝对象共享的子对象是不可变的,将不会产生任何问题。例如,子对象属于像String类这样的不可改变的类;也有可能子对象在其生命周期内不会发生变化,既没有更改它们的方法,也没有创建对它引用的方法。但是,更常见的情况是子对象可变,因此必须重新定义 clone 方法,以便实现克隆子对象的深拷贝。
(3)接口与回调
(4)内部类(实用性?)
- what:内部类是定义在另一个类中的类。
- why,主要原因有三点:
- 内部类的方法可以访问该类所在的外部类的数据,包括私有的数据。
- 内部类可以对同一个包中的其他类隐藏起来。
- 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较方便。
待补充。。。
(5)代理
- 利用代理可以在运行时创建一个实现了一组给定接口的新类。这种功能只有在编译时无法确定需要实现哪个接口时才有必要使用。
待补充。