接口进阶与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只是调用一个已有方法,用方法引用更简洁。

📖 小节

📝 作业

  1. Lambda练习: 用Lambda实现字符串转大写、求长度、判断是否为空
  2. 集合操作: 用Lambda过滤、转换、排序集合
  3. 自定义函数式接口: 定义一个数学运算接口,用Lambda实现加减乘除

下一课

下一课我们将学习 枚举与内部类,了解Java中的特殊类。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏