一、接口
- 接口中只能有:常量域、未实现的方法。不能包括实例域、静态方法、方法实现,提供实例域和方法实现的任务应该由实现接口的那个类来完成。
- 有些接口只定义了常量,而没有定义方法。但最好不要这样使用接口。
- 接口中的所有方法自动地属于public,接口中的域将被自动设为 public static final。
- 可以将接口看成是没有实例域的抽象类,但是这两个概念还是有一定区别的。
- 接口与抽象类的最大区别是:接口可以多继承,而所有类包括抽象类只能单继承。
1.实现接口的步骤
为了让类实现一个接口,通常需要下面两个步骤∶
- 将类声明为实现给定的接口。
- 对接口中的所有方法进行实现。
class Employee implements Comparable{
//将类声明为实现给定的接口
public int compareTo(Object otherObject){
//实现接口中的方法
…………
}
}
需要注意的是,接口中方法没用关键字修饰,但默认是public;实现类中,方法一定要用public修饰,因为如果不用任何关键字修饰则默认是包可见。总之,实现类的可见性不能比抽象类的低,子类的可见性不能比父类的低。
有必要考虑泛型:
class Employee implements Comparable<Employee>{
//将类声明为实现给定的接口
public int compareTo(Employee otherObject){
//实现接口中的方法
…………
}
}
2.接口的特性
- 接口不是类,尤其不能使用 new 运算符实例化一个接口∶
x = new Comparable(...); // ERROR
- 然而,尽管不能构造接口的对象,却能声明接口的变量∶
Comparable x; // 0K
- 接口变量必须引用实现了接口的类对象。
- 接下来,如同使用 instanceof检查一个对象是否属于某个特定类一样,也可以使用 instance 检查一个对象是否实现了某个特定的接口∶
if (an0bject instanceof Comparable){
...}
- 接口之间可以继承,并且一个接口可以继承多个接口。
二、对象克隆
由于对象的复制只能拷贝引用,所以我们用clone()方法来拷贝对象指向的值。
但是,默认的克隆操作是浅拷贝,它并没有克隆包含在对象中的内部对象。也就是说,如果对象的指向仍是引用对象,拷贝的是它的引用。
如果进行浅拷贝会发生什么呢?这要根据具体情况而定。如果原始对象与浅克隆对象共享的子对象是不可变的,将不会产生任何问题。但更常见的情况是子对象可变,因此必须重新定义 clone 方法,以便实现克隆子对象的深拷贝。
即使clone 的默认实现(浅拷贝)能够满足需求,也应该实现 Cloneable接口,将clone重定义为 public,并调用 super.clone( )。下面是一个示例∶
class Employee inplements Cloneable
{
……
public Employee clone() throws CloneNotSupportedException //如果在方法中没有实现clone方法,就会抛出异常
{
Employee cloned = (Employee)super.clone();
cloned.hireDay=(Date)hireDay.clone();
return cloned;
}
}
clone方法多少有些笨重,我们应该避免使用它。
三、内部类
内部类是定义在另一个类中的类。
1.常规内部类
- 内部类既可以访问自身的数据域,也可以访问创建它的外围类对象的数据域。
- 内部类声明为私有的,使得只有其外部类能访问它。只有内部类可以是私有类,而常规类只可以具有包可见性,或公有可见性。
- 在类中如何使用外部类引用:外部类名.this
- 外部类、内部类的引用:
OuterClass o1=new OuterClass();
OuterClass.InnerClass o2= o1.new InnerClass();
2.局部内部类
- 可以在一个类的方法中定义局部内部类。
- 局部内部类可以访问方法的参数,但该参数必须被声明为final。
class Outer
{
public void start(int i,final int j)//内部类能访问j,但无论如何j是不可以修改的
{
class Inner
{
public int getJ()
{
return j;
}
}
}
}
3.匿名内部类
将局部内部类的使用再深入一步,假如只创建这个类的一个对象,就不必命名了,这种类被称为匿名内部类。
public void start(int interval,final boolean beep)
{
//匿名内部类的实现,不一定是要实现一个接口,也可以是一个类,在花括号中需要对该类进行扩展
ActionListener listener = new ActionListener()
{
public void ationPerformed(ActionEvent event){
//由于ActionListener是一个接口,需要实现接口的方法
……
}
}
}
4.静态内部类
有时候,使用内部类只是为了把一个类隐藏在另外一个类的内部,并不需要内部类引用外围类对象。为此,可以将内部类声明为 static,以便取消产生的引用。
静态内部类的对象除了没有对生成它的外围类对象的引用特权外,与其他所有内部类完全一样。
若一个类对象是在静态方法中构造的,则对应的该类只能是静态内部类。只有内部类可以声明为 static。