当前位置: 首页 > web >正文

《Java 程序设计》第 10 章 - 接口与 Lambda 表达式

        大家好!今天我们来学习 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; }@Overridepublic 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 解决默认方法冲突

当类实现的多个接口出现同名默认方法时,遵循以下规则:

  1. 类优先(优先选择父类的方法);

  2. 否则必须手动重写,使用 接口名.super.方法() 指定。

interface A {default void hello() { System.out.println("A"); }
}
interface B {default void hello() { System.out.println("B"); }
}
class C implements A, B {@Overridepublic 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;}@Overridepublic int compareTo(Student o) {return Integer.compare(this.score, o.score); // 升序}@Overridepublic 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; }@Overridepublic int compareTo(Student o) {return Integer.compare(this.score, o.score); // 自然排序:分数升序}@Overridepublic 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>() {@Overridepublic boolean test(String s) {return s.length() > 3;}};// 2. LambdaPredicate<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)

需求:

  1. 定义接口 Payabledouble calcSalary()

  2. SalariedEmployee(固定工资)、HourlyEmployee(时薪)实现接口;

  3. 用 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;}@Overridepublic double calcSalary() {return monthSalary;}@Overridepublic 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;}@Overridepublic double calcSalary() {return hours * rate;}@Overridepublic 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 即可体验。欢迎评论区交流!

http://www.xdnf.cn/news/16782.html

相关文章:

  • HTML基础P2 | JS基础讲解
  • JSON.parse解析大整数踩坑
  • 重生之我在10天内卷赢C++ - DAY 1
  • 安全和AI方向的学习路线
  • Tdesign-React 模板面包屑如何放到 Header头部
  • 白话容器基础(一):进程
  • 2025年6月电子学会青少年软件编程(C语言)等级考试试卷(一级)
  • SSRF漏洞基础
  • Akamai CloudTest before 60 2025.06.02 XXE注入导致文件包含漏洞(CVE-2025-49493)
  • Solon v3.4.2(Java 应用开发生态基座)
  • T113-i Linux系统完整构建指南:从SDK开箱到内核镜像量产烧录全流程
  • 【力扣热题100】哈希——最长连续序列
  • MSVC编译KDChart过程
  • 实现了加载 正向 碰撞 雅可比 仿真
  • [SKE]UVM环境下OpenSSL加密算法参考模型设计
  • BOSMA博冠8K广播级讯道摄像机DC0300 EFP产品画册(下)
  • 利用SQL文件上传注入植入WebShell
  • 【从零实践Onvif】01、Onvif详细介绍(从Onvif客户端开发的角度认识Onvif、Web Servies、WSDL、SOAP)
  • SpringCloud -- MQ高级
  • 数学建模——01规划/整数规划
  • Vue3 Composition API
  • Oracle迁移PostgreSQL隐式类型转换配置指南
  • RHCA - CL260 | Day03:配置 RHCS 集群
  • PyTorch 生态四件套:从图片、视频到文本、语音的“开箱即用”实践笔记
  • Git LFS 安装和使用
  • 动态规划Day5学习心得
  • 原生C++实现信号与槽机制:原理详解
  • windows环境下MySQL 8.0 修改或重置密码
  • SpringBoot 实现 RAS+AES 自动接口解密
  • 图像处理控件Aspose.Imaging教程:使用 C# 编程将 CMX 转换为 PNG