接口进阶与Lambda
本课学习接口的高级特性和Lambda表达式,让代码更简洁。
接口默认方法
Java 8引入默认方法,接口可以有方法体。
语法
JAVA
public interface MyInterface {
// 抽象方法
void abstractMethod();
// 默认方法
default void defaultMethod() {
System.out.println("默认实现");
}
}
示例:默认方法
JAVA
public interface Vehicle {
void start();
default void horn() {
System.out.println("嘀嘀!");
}
default void stop() {
System.out.println("车辆停止");
}
}
public class Car implements Vehicle {
@Override
public void start() {
System.out.println("汽车启动");
}
// 可以选择重写默认方法
@Override
public void horn() {
System.out.println("嘟嘟!");
}
}
public class DefaultMethodDemo {
public static void main(String[] args) {
Car car = new Car();
car.start(); // 汽车启动
car.horn(); // 嘟嘟!(重写后的方法)
car.stop(); // 车辆停止(接口默认实现)
}
}
接口静态方法
Java 8引入静态方法,通过接口名直接调用。
JAVA
public interface MathUtils {
static int add(int a, int b) {
return a + b;
}
static int multiply(int a, int b) {
return a * b;
}
}
public class StaticMethodDemo {
public static void main(String[] args) {
System.out.println(MathUtils.add(3, 5)); // 8
System.out.println(MathUtils.multiply(3, 5)); // 15
}
}
函数式接口
只有一个抽象方法的接口,可以用Lambda表达式实现。
@FunctionalInterface注解
JAVA
@FunctionalInterface
public interface Calculator {
int calculate(int a, int b);
}
常见函数式接口
| 接口 | 方法 | 说明 |
|---|---|---|
Predicate<T> |
boolean test(T t) |
判断 |
Function<T,R> |
R apply(T t) |
转换 |
Consumer<T> |
void accept(T t) |
消费 |
Supplier<T> |
T get() |
提供 |
Lambda表达式
Lambda是匿名函数的简写,Java 8引入。
语法
JAVA
(参数列表) -> { 方法体 }
示例:Lambda
JAVA
// 传统方式
Calculator add = new Calculator() {
@Override
public int calculate(int a, int b) {
return a + b;
}
};
// Lambda表达式
Calculator add = (a, b) -> a + b;
// 调用
int result = add.calculate(3, 5); // 8
Lambda的多种形式
JAVA
// 无参数
Runnable r = () -> System.out.println("Hello");
// 一个参数
Consumer<String> print = s -> System.out.println(s);
// 多个参数
Comparator<String> comp = (a, b) -> a.length() - b.length();
// 多行语句
Function<String, String> upper = s -> {
String result = s.trim();
return result.toUpperCase();
};
示例:Lambda使用
JAVA
import java.util.Arrays;
import java.util.List;
import java.util.function.*;
public class LambdaDemo {
public static void main(String[] args) {
// Predicate:判断
Predicate<Integer> isEven = n -> n % 2 == 0;
System.out.println(isEven.test(4)); // true
System.out.println(isEven.test(7)); // false
// Function:转换
Function<String, Integer> length = s -> s.length();
System.out.println(length.apply("Hello")); // 5
// Consumer:消费
Consumer<String> print = s -> System.out.println("输出:" + s);
print.accept("Java"); // 输出:Java
// Supplier:提供
Supplier<Double> random = () -> Math.random();
System.out.println(random.get());
}
}
Lambda与集合
Lambda让集合操作更简洁。
示例:遍历
JAVA
import java.util.Arrays;
import java.util.List;
public class LambdaCollection {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 传统方式
for (String name : names) {
System.out.println(name);
}
// Lambda方式
names.forEach(name -> System.out.println(name));
// 方法引用(更简洁)
names.forEach(System.out::println);
}
}
示例:排序
JAVA
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class LambdaSort {
public static void main(String[] args) {
List<String> names = Arrays.asList("Charlie", "Alice", "Bob");
// 传统方式
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.compareTo(b);
}
});
// Lambda方式
names.sort((a, b) -> a.compareTo(b));
// 方法引用
names.sort(String::compareTo);
System.out.println(names); // [Alice, Bob, Charlie]
}
}
方法引用
方法引用是Lambda的简写形式。
四种方法引用
| 类型 | 语法 | 示例 |
|---|---|---|
| 静态方法 | 类名::静态方法 |
Math::abs |
| 实例方法 | 对象::实例方法 |
System.out::println |
| 特定类 | 类名::实例方法 |
String::length |
| 构造方法 | 类名::new |
ArrayList::new |
示例:方法引用
JAVA
import java.util.Arrays;
import java.util.List;
import java.util.function.*;
public class MethodRefDemo {
public static void main(String[] args) {
// 静态方法引用
Function<Integer, Integer> abs = Math::abs;
System.out.println(abs.apply(-5)); // 5
// 实例方法引用
Consumer<String> print = System.out::println;
print.accept("Hello"); // Hello
// 特定类实例方法引用
Function<String, Integer> length = String::length;
System.out.println(length.apply("Hello")); // 5
// 构造方法引用
Supplier<List<String>> listFactory = ArrayList::new;
List<String> list = listFactory.get();
}
}
综合示例
JAVA
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class LambdaPractice {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 过滤偶数
List<Integer> evens = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println("偶数:" + evens); // [2, 4, 6, 8, 10]
// 平方
List<Integer> squares = numbers.stream()
.map(n -> n * n)
.collect(Collectors.toList());
System.out.println("平方:" + squares); // [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
// 求和
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
System.out.println("求和:" + sum); // 55
// 最大值
int max = numbers.stream()
.reduce(Integer::max)
.orElse(0);
System.out.println("最大值:" + max); // 10
}
}
❓ 常见问题
Q Lambda和匿名内部类有什么区别?
A Lambda更简洁,只能用于函数式接口。匿名内部类可以用于任何接口或类。
Q 什么时候用Lambda?
A 实现函数式接口时,特别是集合操作、事件处理等场景。
Q 方法引用和Lambda怎么选?
A 如果Lambda只是调用一个已有方法,用方法引用更简洁。
📖 小节
- 接口默认方法:Java 8引入,接口可以有方法体
- 接口静态方法:通过接口名直接调用
- 函数式接口:只有一个抽象方法的接口
- Lambda表达式:匿名函数的简写
- 方法引用:Lambda的简写形式
📝 作业
- Lambda练习: 用Lambda实现字符串转大写、求长度、判断是否为空
- 集合操作: 用Lambda过滤、转换、排序集合
- 自定义函数式接口: 定义一个数学运算接口,用Lambda实现加减乘除
下一课
下一课我们将学习 枚举与内部类,了解Java中的特殊类。



