摘自 《Java 核心技术(卷 Ⅰ)》

《Java 核心技术(卷 Ⅰ)》
《Java 核心技术(卷 Ⅰ)》

未完待续~

接口、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/CollectionsPath/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 解决默认方法冲突有以下两个规则

  1. 超类优先:如果超类提供了一个具体方法,同名而且有相同参数类型的默认方法会被忽略
  2. 接口冲突:如果一个超接口提供了一个默认方法,另一个接口提供了一个同名而且参数类型相同的方法,必须覆盖这个方法来解决冲突

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 表达式

4. 内部类