1.接口
一个类可以实现一个或多个接口。
接口中的所有方法自动属于public。
接口绝不能含有实例域,也不能在接口中实现方法。
实现接口的步骤:
1)将类声明为实现给定的接口 关键字implements
2)对接口中的所有方法进行定义
警告:在实现接口时,必须把方法声明为public;否则,编译器将认为这个方法的访问属性是包可见性,即类的默认访问属性,之后编译器就会给出试图提供更严格的访问权限的警告信息。
提示:Comparable接口中的compareTo方法将返回一个整数值,两个对象相等将返回0,前者大,返回正值,否则返回负值。
调用Arrays类中的sort方法时,必须使用实现Comparable接口的数组作为sort方法的参数。
当子类重写超类compareTo方法时,比较时注意类型检测。
if(getClass()!=other.getClass()) throw new ClassCastException();
如果存在通用算法能够对两个不同的子类对象进行比较,则应该在超类中提供一个compareTo方法,并将这个方法声明为final。
1.1 接口的特性
接口不是类,不能用new运算符实例化一个接口,可以声明接口的变量。
可以用instanceof检查一个对象是否实现了某个特定的接口。
接口可以扩展。
接口中不能包含实例域和静态方法,但可以包含常量。接口中的域自动声明为public static final。
每个类只能继承一个超类,但可以实现多个接口。
1.2 接口与抽象类
Java不支持多继承,原因是多继承会让语言本身变得非常复杂(C++),效率也会降低(Eiffel)。
2.对象克隆
Object.clone() //访问权限是protected
默认的克隆操作是浅拷贝,他并没有拷贝包含在对象中的内部对象。
更常见的情况是子对象可变,因此,必须重新定义clone方法,以便实现克隆子对象的深拷贝。
对于每一个类,都需要做出下列判断:
1.默认的clone方法是否满足需求
2.默认的clone方法是否能够通过调用可变子对象的clone得到修补
2.默认的clone方法是否能够通过调用可变子对象的clone得到修补
3.是否不应该使用clone
实际上,选项3是默认的。如果选择1或2,类必须:
1.实现Cloneable接口
2.使用 public 访问修饰符重新定义clone方法。
实际上,选项3是默认的。如果选择1或2,类必须:
1.实现Cloneable接口
2.使用 public 访问修饰符重新定义clone方法。
即使clone的默认实现(浅拷贝)能够满足需求,也应该实现Cloneable接口,
将clone重定义为 public,并调用super.clone()。
class Employee implements Cloneable
{
// raise visibility level to public, change return type
public Employee clone() throws CloneNotSupportedException
{
return (Employee)super.clone();
}
}
class Employee implements Cloneable
{
...
public Employee clone() throws CloneNotSupportedException
{
// call Object.clone()
Employee cloned = (Employee)super.clone();
// clone mutable fields
clone.hireDay = (Date)hireDay.clone();
return cloned;
}
}
所有的数组类型均包含一个clone方法,这个方法被设为 public,而不是 protected,可以利用这个方法创建一个包含所有数据元素拷贝的一个新数组。
int[] luckyNumbers = {2, 4, 5};
int[] cloned = luckyNumbers.clone();
cloned[1] = 8; // don't change luckyNumbers[1]
3.内部类
内部类是定义在另一个类中的类。使用内部类的原因:
·内部类方法可以访问该类定义所在作用域中的数据,包括私有的数据
·内部类可以对同一个包中的其他类隐藏起来
·当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。
内部类的对象有一个隐式引用(OuterClass.this),它引用了实例化该内部对象的外围类对象。通过这个指针,可以访问外围类对象的全部状态。
引用内部类:OuterClass.InnerClass
匿名内部类:
public void start(int interval, final boolean beep)
{
ActionListener listener = new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
Date now = new Date();
System.out.println("At the tone, the time is " + now);
if (beep)
Toolkit.getDefaultToolkit().beep();
}
};
Timer t = new Timer(interval, listener);
t.start();
}