一个类可以可以实现一个或多个接口,并在需要接口的地方随时使用实现了相应接口的对象。
6.1
在Java程序设计语言暗中,接口不是类,而是一组对垒的需求描述,这些类药遵从接口描述的统一格式进行定义。我们京城听到服务提供商这样说:”如果你的类遵从某个特定接口,那么我就履行这项服务“。
接口中的所有方法自动地属于public。因此,在接口中声明方法时,不必提供关键字public,但在实现接口时,必须把方法声明为public。在接口中可以定义常量,但在接口中决不能含有实例域,也不能再接口中实现方法。提供实例域和实现方法的任务应该由实现接口的那个类来完成。可以将接口看成是没有实例域的抽象类。但还是有所区别。
为了让类实现一个接口,通常要下面两个步骤:
1)将类声明为实现给定的接口。
2)对接口中的所有方法进行定义。
要将类声明为实现某个接口,需要使用关键字implements:
class Employee implements Comparable
6.1.1接口的特性
接口不是类,尤其是不能使用new运算符实例化一个接口,即不能构造接口对象,却能声明接口变量:
Comparable x;
接口变量必须引用实现了接口的类对象:
x = new Employee(...);
可以扩展接口,如同类的继承。
6.2对象克隆
对每一个类,都需要做出下列判断:
1)默认的clone方法是否满足要求。
2)默认的clone方法是否能够通过调用可变子弟象的clone得到修补。
3)是否不应该使用clone。
实际上,选项3是默认的。如果要选择1或2,类必须:
1)实现Cloneable接口。
2)使用public访问修饰符重新定义clone方法。
子类只能调用受保护的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 super.clone(); } ...... }
|
6.3 接口与回调
回调(callback)是一种常见的程序设计模式。在这种模式中,可以指出某个特定时间发生时应该采取的动作。
6.4 内部类
内部类(inner class)是定义在另一个类中的类。使用内部类主要原因有三:
·内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据。
·内部类可以对同一个包中的其他类隐藏起来。
·当想要个定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。
如果内部类有构造器,编译器将会对它进行修改,并添加一个外围引用的参数。
OuterClass.this 表示外围类引用。
局部内部类(在一个方法中定义的类)不能用public或private访问说明符进行声明。他的作用域被限定在声明该局部类的块中。局部类具有对外界可以完全隐藏的优势。与其他内部类相比,局部还有另一个优势:它们不仅能够访问包含它们的外围类的域,而且还可以访问局部变量!不过,这些局部变量必须被声明为final。
假如只创建局部内部类的一个对象,就不必为它命名了。这种类被称为匿名内部类(anonymous inner class)。
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(1000, listener); t.start(); }
|
它的含义是:创建一个实现ActionListener接口的类地新对象,需要实现的方法actionPerformed定义在括号{}内。用于构造对象的任何参数都要被放在超类名后面的括号()内。
通常的语法格式为:
new SuperType(construction parameters) { inner class methods and data }
|
其中,SuperType可以是ActionListener这样的接口。由于构造器的名字必须与类名相同,而匿名类没有类名,所以,匿名类不能有构造器。取而代之的是,将构造器参数传递给超类构造器。尤其是在内部类实现接口的时候,不能有任何构造参数。
有时候,使用内部类只是为了把一个类隐藏在另一个类的内部,并不需要内部引用外围类对象。为此,可以将内部类声明为static,以便取消产生的引用。
6.5代理
代理(proxy),利用代理可以在运行时船舰一个实现了一组给定接口的新类。这种功能只在编译时无法确定学要实现哪个接口时才有必要使用。
通过使用代理,常常可以避免生成和编译“桩”代码。代理类可以在运行时创建全新的类,这样的代理类能够实现指定的接口。尤其是,它具有下列方法:
·指定接口所需的全部方法。
·Object类中的全部方法。
然而,不能在运行时定义这些方法的新代码。而是要提供一个调用处理器(invocation handler)。调用处理器是实现了InvocationHandler接口的类对象。在这个接口中只有一个方法:
Object invoke(Object proxy, Method method, Object[] args)
要想创建一个代理对象,需要使用Proxy类的newProxyInstance方法。这个方法有三个参数:
·一个类加载器 (class loader)。作为Java安全模型的一部分,对于系统类和从因特网上下载下来的类,可以使用不同的类加载器。目前,用null表示使用默认的类加载器。
·一个Class对象数足,每个元素都是需要实现的接口。
·一个调用处理器。
阅读(531) | 评论(0) | 转发(0) |