未完待续~
接口、lambda 表达式与内部类
1. 接口
1.1 接口概念
接口(interface)技术主要用来描述类具有什么功能,而并不给出每个功能的具体实现。
一个类可以实现(implement)一个或多个接口,并在需要接口的地方,随时使用实现了相应接口的对象。
在 Java 程序设计语言中,接口不是类,而是对类的一组需求描述,这些类要遵从接口描述的统一格式进行定义。
public interface Comparable {
int compareTo(Object other);
}
接口中的所有方法都会自动的属于 public。因此,在接口中声明方法时,不必提供关键字 public。
除此之外,有些接口可能包含多个方法。在接口中还可以定义常量。然而,接口绝不能包含有实例域。
要将类声明为实现某个接口,需要使用关键字 implements:
class Employee implements Comparable
1.2 接口的特性
接口不是类,尤其不能使用 new 运算符实例化一个接口:
x = new Comparable(...); // ERROR
然而,尽管不能构造接口的对象,却能声明接口的变量:
Comparable x; // OK
接口变量必须引用实现了接口的类对象:
x = new Employee(...); // OK provided Employee implements Comparable
类似的,可以使用instanceof
检查一个对象是否实现了某个特定的接口:
if (anObject instanceof Comparable) {...}
与建立类的继承关系一样,接口也可以被扩展。
与接口中的方法都自动的被设置为 public 一样,接口中的域将被自动设为 public static final。
1.3 接口与抽象类
使用抽象类表示通用属性存在这样一个问题:每个类只能扩展于一个类;但每个类可以实现多个接口。
Java 的设计者选择了不支持多继承(multiple inheritance),其主要原因是多继承会让语言本身变得非常复杂,效率也会降低。
事实上,接口可以提供多重继承的大多数好处,同时还能避免多重继承的复杂性和低效性。
1.4 静态方法
在 Java SE 8中,允许在接口中增加静态方法。目前为止,通常的做法都是将静态方法放在伴随类中。在标准库中,你会看到成对出现的接口和实用工具类,如Collection/Collections
或Path/Paths
。
1.5 默认方法
可以为接口方法提供一个默认实现,必须用 default 修饰符标记:
public interface Comparable<T> {
default int compareTo(T other) {
return 0;
}
// By default, all elements are the same
}
1.6 解决默认方法冲突
如果先在一个接口中将一个方法定义为默认方法,然后又在超类或另一个接口中定义了同样的方法,就会发生冲突。Java 解决默认方法冲突有以下两个规则:
- 超类优先:如果超类提供了一个具体方法,同名而且有相同参数类型的默认方法会被忽略
- 接口冲突:如果一个超接口提供了一个默认方法,另一个接口提供了一个同名而且参数类型相同的方法,必须覆盖这个方法来解决冲突
2. 接口示例
2.1 接口与回调
回调(callback)是一种常见的程序设计模式。在回调中,可以指出某个特定时间发生时应该采取的动作。
例如,java.swing
包中有一个 Timer 定时器类,它需要知道调用哪一个方法,并要求传递的对象所属的类实现了java.awt.event
包的 ActionListener 接口:
package timer;
/**
@version 1.01 2015-05-12
@author Cay Horstmann
*/
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
// to resolve conflict with java.util.Timer
public class TimerTest
{
public static void main(String[] args)
{
ActionListener listener = new TimePrinter();
// construct a timer that calls the listener
// once every 10 seconds
Timer t = new Timer(10000, listener);
t.start();
JOptionPane.showMessageDialog(null, "Quit program?");
System.exit(0);
}
}
class TimePrinter implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
System.out.println("At the tone, the time is " + new Date());
Toolkit.getDefaultToolkit().beep();
}
}
2.2 Comparator 接口
假设我们希望按长度递增的顺序对字符串进行排序,Arrays.sort
方法还有第二个版本,有一个数组和一个比较器(comparator)作为参数,比较器是实现了 Comparator 接口的类的实例:
public interface Comparator<T> {
int compare(T first, T second);
}
要按长度比较字符串,可以如下定义一个实现 Comparator
class LengthComparator implements Comparator<String> {
public int compare(String first, String second) {
return first.length() - second.length();
}
}
具体完成比较时,需要建立一个实例:
Comparator<String> comp = new LengthComparator();
if (comp.compare(words[i], words[j]) > 0) ...
2.3 对象克隆
略
3. lambda 表达式
略