子父类是包含关系,接口用于关系网。
接口与实现
相关主线:面对对象的程序与设计(基础入门)、抽象类、多态
接口(Interface)
- 在Java中,接口是一种引用类型,用于定义一组抽象方法(Java 8+ 支持默认方法、静态方法、私有方法)。
- 使用关键字
interface声明。 - 所有方法默认是
public abstract,字段(变量)默认是public static final(因此是常量),因此继承重写时方法需public。 - 接口中变量默认public,static,final
- 抽象方法不能被
static和final修饰。 - 接口没有构造函数
default 方法(接口默认方法)
- 是什么:Java 8 引入,用
default关键字声明,方法体必须存在。 - 为什么:在不破坏已有实现类的前提下,向接口添加新方法。
- 怎么用:
- 实现类可继承默认实现,也可重写。
- 重写时可选调用原接口的默认方法:
接口名.super.方法()。
- 冲突:一个类实现多个接口,若多个接口有同名 default 方法,则必须在类中重写,否则编译报错。
- 注意:default 方法不能访问实例字段(接口无实例字段),且与
Object类的方法(如toString)冲突时,实现接口的子类优先采用Object的。
定义接口
public interface Flyable {
void fly(); // 抽象方法
default void glide() { // 默认方法
System.out.println("滑翔中...");
}
static void info() { // 静态方法
System.out.println("Flyable 接口");
}
}实现接口(Implements)
- 类通过
implements关键字实现一个或多个接口。 - 必须实现接口中所有的抽象方法(除非类是抽象类)。
- 必须实现final常量
- default也继承,可理解为有默认方法体的abstract void
- 重写时不可省略public(不能降低访问权限)
- 类继承接口时继承除static、private的方法
- 不能继承接口常量,只是能够调用接口常量
抽象类实现接口
抽象类实现接口时,可以只实现部分抽象方法,未实现的自动成为该抽象类的抽象方法,继续传递给子类。同时,抽象类可以:
- 直接继承接口的 default 方法(无需实现)。
- 无法继承接口的 static 方法(只能通过接口名调用)。
- 重写 default 方法,也可在其中调用
接口名.super.方法()。
这种机制使抽象类在接口与具体类之间充当部分实现者,适合定义通用行为、保留可变部分由子类定制。
public class Bird implements Flyable {
@Override
public void fly() {
System.out.println("鸟在飞");
}
}接口回调(Interface Callback)
- 定义:将实现了某个接口的对象引用传递给另一个方法,由该方法在适当时候回调该接口中定义的方法。
- 本质:一种解耦的设计模式——调用方只依赖接口,不关心具体实现类。
- 典型场景:按钮点击事件、异步任务完成后通知。
- 示例:
interface Callback { void onComplete(String result); } class Task { void execute(Callback cb) { // 执行任务... cb.onComplete("完成"); // 回调 } } class Main implements Callback { public void onComplete(String result) { System.out.println(result); } public static void main(String[] args) { new Task().execute(new Main()); // 传入回调对象 } } - 特点:实现类不知道回调何时被触发,只负责实现接口方法;触发时机由调用方决定。
函数式接口与 Lambda 表达式
函数式接口(Functional Interface)
- 定义:只包含一个抽象方法的接口(可以有 default、static 方法)。
- 注解:
@FunctionalInterface(可选,加上的话编译器会检查是否符合函数式接口规范)。 - 常见内置函数式接口:
| 接口 | 方法 | 用途 |
|---|---|---|
Runnable | void run() | 无参无返回值 |
Supplier<T> | T get() | 提供者,无参有返回值 |
Consumer<T> | void accept(T t) | 消费者,有参无返回值 |
Function<T,R> | R apply(T t) | 类型转换,有参有返回值 |
Predicate<T> | boolean test(T t) | 判断,有参返回 boolea n |
Lambda 表达式
面向只有一个抽象方法的接口(只需要重写一个抽象方法),用于简化代码 匿名类 上下文推断输入类型
- 本质:函数式接口的简洁写法,替代匿名内部类,指代对应接口或父类的子类。
- 语法:
(参数列表) -> { 方法体 }- 参数类型可省略(编译器推断)。
- 单参数可省略括号(如
x -> x * 2)。 - 单行方法体可省略花括号和
return。
- 示例:
// 匿名内部类写法
Runnable r1(变量名被赋予引用地址) = new Runnable() {
@Override
public void run() {
System.out.println("run");
}
};
// Lambda 写法
Runnable r2 = () -> System.out.println("run");// 比较器
Comparator<String> comp = (s1, s2) -> s1.length() - s2.length();方法引用(Method Reference)
- Lambda 的进一步简化,当 Lambda 体只是调用一个现有方法时使用。
- 格式:
类名::方法名或对象::方法名。
| 类型 | 示例 | 等价 Lambda |
|---|---|---|
| 静态方法 | Integer::parseInt | s -> Integer.parseInt(s) |
| 实例方法(特定对象) | System.out::println | x -> System.out.println(x) |
| 实例方法(任意对象) | String::length | s -> s.length() |
| 构造器 | ArrayList::new | () -> new ArrayList<>() |
注意
- Lambda 表达式只能用于函数式接口。
- Lambda 中引用的局部变量必须是 final 或 effectively final(不可被后续修改)。
接口的特性
- 多继承:一个类可以实现多个接口,弥补单继承的不足。(关系网)
- 接口可以继承接口:使用
extends关键字,支持多继承。 - 默认方法:提供默认实现,子类可以重写或直接使用。
- 静态方法:不能被子类继承或重写,只能通过接口名调用。
- 私有方法(Java 9+):用于在接口内部复用代码,不对外暴露。
接口 vs 抽象类
| 特性 | 接口 | 抽象类 |
|---|---|---|
| 关键字 | interface | abstract class |
| 构造器 | 无 | 有 |
| 多继承 | 支持(类可以实现多个接口) | 不支持(单继承) |
| 字段 | 只能是 public static final | 可以有实例变量 |
| 方法 | 抽象方法、默认、静态、私有 | 抽象方法、具体方法 |
使用场景
- 定义行为规范(如可飞行、可比较
Comparable)。 - 实现松耦合设计(面向接口编程)。
- 利用默认方法在不破坏现有实现的前提下扩展接口功能。