大家好!今天我们来学习 Java 中的接口与 Lambda 表达式。这两个特性在 Java 编程中非常重要,尤其是 Lambda 表达式,它是 Java 8 引入的新特性,极大地简化了代码编写。话不多说,让我们开始吧!
思维导图
10.1 接口
10.1.1 接口定义
接口(interface)是纯粹的抽象类型,所有成员默认 public
(JDK 8 以前)。
语法:
[public] interface 接口名 [extends 父接口列表] {
// 1. 抽象方法(可省略 public abstract)
返回类型 方法名(参数列表);
// 2. 常量(默认 public static final)
类型 常量名 = 值;
}
10.1.2 接口的实现
类通过 implements
关键字实现接口,必须实现所有抽象方法。
示例:
// 文件:Drawable.java
public interface Drawable {
void draw(); // 抽象方法
String DEFAULT_COLOR = "BLACK"; // 常量
}
// 文件:Circle.java
public class Circle implements Drawable {
private double r;
public Circle(double r) { this.r = r; }
@Override
public void draw() {
System.out.println("画一个半径为 " + r + " 的圆,颜色:" + DEFAULT_COLOR);
}
public static void main(String[] args) {
new Circle(3.5).draw();
}
}
10.1.3 接口的继承
接口可多重继承,形成“继承链”。
interface A { void a(); }
interface B { void b(); }
interface C extends A, B { void c(); } // C 拥有 a() b() c()
10.1.4 接口类型的使用
接口变量可指向任何实现类对象——多态的核心。
Drawable d = new Circle(2);
d.draw(); // 运行时调用 Circle 的实现
10.1.5 常量
接口中的变量默认 public static final
,一般用于全局常量池。
10.2 静态方法和默认方法
10.2.1 静态方法
JDK 8 起允许接口定义 static
方法,只能通过接口名调用。
public interface Logger {
static void info(String msg) {
System.out.println("[INFO] " + msg);
}
}
// 调用
Logger.info("系统启动");
10.2.2 默认方法
default
方法提供默认实现,实现类可重写也可直接使用。
public interface Animal {
default void breathe() {
System.out.println("用肺呼吸");
}
}
10.2.3 解决默认方法冲突
当类实现的多个接口出现同名默认方法时,遵循以下规则:
类优先(优先选择父类的方法);
否则必须手动重写,使用
接口名.super.方法()
指定。
interface A {
default void hello() { System.out.println("A"); }
}
interface B {
default void hello() { System.out.println("B"); }
}
class C implements A, B {
@Override
public void hello() {
A.super.hello(); // 显式指定
}
}
10.3 接口示例
10.3.1 Comparable 接口
让对象具备自然排序能力。
import java.util.*;
public class Student implements Comparable<Student> {
private String name;
private int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public int compareTo(Student o) {
return Integer.compare(this.score, o.score); // 升序
}
@Override
public String toString() {
return name + ":" + score;
}
public static void main(String[] args) {
// 1. 用 new ArrayList<>(...) 包装,变成可变列表
List<Student> list = new ArrayList<>(List.of(
new Student("Alice", 90),
new Student("Bob", 70),
new Student("Carol", 95)
));
// 2. 排序
Collections.sort(list);
// 3. 打印
list.forEach(System.out::println);
}
}
10.3.2 Comparator 接口
当需要多种排序策略时使用,更灵活。
// 文件:Student.java
import java.util.*;
public class Student implements Comparable<Student> {
private String name;
private int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
/* ===== 新增 getter ===== */
public String getName() { return name; }
public int getScore() { return score; }
@Override
public int compareTo(Student o) {
return Integer.compare(this.score, o.score); // 自然排序:分数升序
}
@Override
public String toString() {
return name + ":" + score;
}
}
// 文件:StudentComparator.java
import java.util.*;
public class StudentComparator {
public static void main(String[] args) {
// 用 new ArrayList<>(...) 把不可变列表变成可变
List<Student> list = new ArrayList<>(List.of(
new Student("Alice", 90),
new Student("Bob", 70),
new Student("Carol", 95)
));
// 1. 按姓名升序
list.sort(Comparator.comparing(Student::getName));
System.out.println("按姓名升序:");
list.forEach(System.out::println);
// 2. 按分数降序
list.sort(Comparator.comparingInt(Student::getScore).reversed());
System.out.println("按分数降序:");
list.forEach(System.out::println);
}
}
10.4 Lambda 表达式
10.4.1 Lambda 简介
Lambda 是匿名函数,用于简化函数式接口的实例化。
10.4.2 函数式接口
仅含一个抽象方法的接口,可用 @FunctionalInterface
标注。
10.4.3 Lambda 语法
(parameters) -> { statements }
10.4.4 预定义的函数式接口
接口名 | 抽象方法 | 用途示例 |
---|---|---|
Predicate<T> | boolean test(T t) | 过滤 |
Function<T,R> | R apply(T t) | 转换 |
Consumer<T> | void accept(T t) | 消费 |
Supplier<T> | T get() | 生产 |
10.4.5 方法引用与构造方法引用
方法引用:
类::方法
构造引用:
类::new
示例:使用 Lambda + 方法引用过滤列表
import java.util.*;
import java.util.function.Predicate;
public class LambdaDemo {
public static void main(String[] args) {
List<String> list = Arrays.asList("Java", "Python", "Go", "C++");
// 1. 匿名类
Predicate<String> p1 = new Predicate<String>() {
@Override
public boolean test(String s) {
return s.length() > 3;
}
};
// 2. Lambda
Predicate<String> p2 = s -> s.length() > 3;
// 3. 方法引用
Predicate<String> p3 = LambdaDemo::isLongName;
list.stream().filter(p3).forEach(System.out::println);
}
private static boolean isLongName(String s) {
return s.length() > 3;
}
}
10.5 小结
接口:解耦、多继承、常量池;
默认/静态方法:增强接口能力;
Comparable & Comparator:两种排序策略;
Lambda:函数式编程利器,简化代码。
编程练习
练习 1:员工薪资处理(接口 + Lambda)
需求:
定义接口
Payable
含double calcSalary()
;类
SalariedEmployee
(固定工资)、HourlyEmployee
(时薪)实现接口;用 Lambda 计算全体员工总薪资并过滤高薪员工(> 20000)。
完整代码:
// 文件:Payable.java
@FunctionalInterface
public interface Payable {
double calcSalary();
}
// 文件:SalariedEmployee.java
public class SalariedEmployee implements Payable {
private double monthSalary;
public SalariedEmployee(double monthSalary) {
this.monthSalary = monthSalary;
}
@Override
public double calcSalary() {
return monthSalary;
}
@Override
public String toString() {
return "SalariedEmployee: " + monthSalary;
}
}
// 文件:HourlyEmployee.java
public class HourlyEmployee implements Payable {
private double hours;
private double rate;
public HourlyEmployee(double hours, double rate) {
this.hours = hours;
this.rate = rate;
}
@Override
public double calcSalary() {
return hours * rate;
}
@Override
public String toString() {
return "HourlyEmployee: " + calcSalary();
}
}
// 文件:PayrollSystem.java
import java.util.*;
import java.util.stream.Collectors;
public class PayrollSystem {
public static void main(String[] args) {
List<Payable> employees = List.of(
new SalariedEmployee(18000),
new HourlyEmployee(160, 100),
new SalariedEmployee(25000),
new HourlyEmployee(200, 120)
);
// 总薪资
double total = employees.stream()
.mapToDouble(Payable::calcSalary)
.sum();
System.out.println("总薪资 = " + total);
// 高薪员工
List<Payable> high = employees.stream()
.filter(e -> e.calcSalary() > 20000)
.collect(Collectors.toList());
high.forEach(System.out::println);
}
}
运行结果:
① 思维导图:接口与 Lambda 学习路线
② 接口继承关系类图(PlantUML)
@startuml
interface Drawable
interface Colorable
interface Paintable extends Drawable, Colorable
class Circle implements Paintable
@enduml
③ Lambda 表达式执行流程图
结语
复制代码直接 javac *.java
即可体验。欢迎评论区交流!