文章目录
第六章 接口、lambda表达式与内部类
- 接口: 描述类应该做什么, 不指定如何做
- lambda表达式: 表示使用回调或者可变行为的代码
接口
接口的概念
-
接口
: 不是类, 而是对希望符合这个接口的类的一组需求 -
Arrays
类中的sort
方法对对象数组进行排序, 要求对象所属的内必须实现Comparable
接口
public interface Comparable
{
int compareTo(Object other);
}
//java5后
public interface Comparable<T>
{
int compareTo(T other);
}
- 接口中的所有方法自动为
public
- 接口中可以包含多个方法, 但是接口不会有实例字段
- 让一个类实现一个接口:
- 将类声明为实现给定的接口
- 对接口中的所有方法提供定义
- 将类声明为实现为某个接口, 使用关键字
implements
class Employee implements Comparable
Java API
建议equals, compareTo
方法兼容- 例外:
x = BigDecimal("1.0"); y = BigDecimal("1.00"); x.equals(y)//false x.compareTo(y) == 0
package chapter6_interface_lambda_innerClass.interfaces;
public class Employee implements Comparable<Employee>{
private String name;
private double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public double getSalary() {
return salary;
}
public String getName() {
return name;
}
public int compareTo(Employee other) {
return Double.compare(salary, other.salary);
}
}
package chapter6_interface_lambda_innerClass.interfaces;
import java.util.Arrays;
public class EmployeeSortTest {
public static void main(String[] args) {
var staff = new Employee[3];
staff[0] = new Employee("Oukunnan", 25598);
staff[1] = new Employee("Ovfdunnan", 18);
staff[2] = new Employee("dsukunnan", 98);
Arrays.sort(staff);
for (Employee employee : staff) {
System.out.println(employee.getName() + " salary=" + employee.getSalary());
}
}
}
接口的属性
- 接口不是类, 不能用
new
运算符实例化一个接口 - 能够声明接口变量:
Comparable x ; //OK
- 接口变量必须引用实现了这个接口的类对象
x = new Employee(...);
instanceof
: 1. 检查一个对象是否属于某个特定的类 2. 一个对象是否实现了某个特定的接口
if (anObject instanceof Comparable){
...};
- 与建立类的继承层次类似, 可以扩展接口
public interface Moveable{
...}
public interface Powered extends Moveable{
..}
- 接口不能包含实例字段但是可以包含常量
- 接口的方法总是
public
, 接口的字段总是public static final
, 都可以省略, 建议省略 - 每个类只有一个超类, 却可以实现多个接口, 有点像
C++
的多重继承
接口与抽象类
- 抽象类问题: 每个类只能扩展一个类
- java可以扩展一个基类并且派生多个接口
静态和私有方法
- 标准库中成对出现的接口和实用工具类:
Collection/Collections, Path/paths
- 允许在接口中增加静态方法, 一般做法是放在伴随类中
- java9中接口中的方法可以是
private
默认方法
- 接口方法提供一个默认实现,
default
修饰符标记
public interface Comparable<T>
{
default int CompareTo(T other) {
return 0;}
}
-
如果迭代器是只读的就不用实现
remove
方法public interface Iterator<E> { boolean hasNext(); E next(); default void remove(){ throw new UnsupprotedOperationException("remove");} }
-
另一个作用是接口演化, 实现源代码兼容
解决默认方法冲突
- 超类优先
- 同时实现的两个接口中由完全同名并且参数类型相同的方法, 要求这个类实现该方法覆盖接口的方法
class Student extends Person implements Named{...}
只会考虑超类方法, 类优先原则
接口与回调
回调
: 指定某个特定事件发生时应该采取的动作
package chapter6_interface_lambda_innerClass.timer;
import java.awt.event.*;
import java.awt.*;
import java.time.*;
import javax.swing.*;
public class TimerTest {
public static void main(String[] args) {
var listener = new TimePrinter();
var timer = new Timer(1000, listener);//每隔1000ms(1s)响铃并且打应输出
timer.start();
JOptionPane.showMessageDialog(null, "Quit Program?");//展示消息框
System.exit(0);
}
}
class TimePrinter implements ActionListener {
public void actionPerformed(ActionEvent event) {
//ActionEvent 事件参数,提供事件的相关信息 //getWhen的得到纪元以来的毫秒数, 利用函数转换成可读时间
System.out.println("At this tone, the time is " + Instant.ofEpochMilli(event.getWhen()));
Toolkit.getDefaultToolkit().beep(); //调用默认工具箱响铃
}
}
Comparator
接口
- 对于对象数组进行排序, 前提是这些对象是实现了
Comparable
接口类的实例 - 如果按照长度而不是字典顺序对于字符串进行排序, 使用
Arrays.sort
的另一种版本, 一个数组和比较器作为参数 - 比较器实现
Comparator
接口
public interface Comparator<T>
{
int compare(T first, T second);
}
class LengthComparator