接口、泛型与函数式接口

接口、泛型与函数式接口

接口定义能力契约。类可以实现多个接口,从而获得多态能力而不受单继承限制。

接口语法

代码块JAVA · 11 行收起展开
public interface PaymentService {
    Receipt pay(Order order);

    default boolean supports(Order order) {
        return order != null;
    }

    static PaymentService noop() {
        return order -> Receipt.empty();
    }
}
  • 抽象方法默认 public abstract。
  • 字段默认 public static final,必须初始化。
  • default 方法提供可继承实现。
  • static 方法属于接口本身。
  • private 方法可供接口内部复用。
  • 函数式接口只有一个抽象方法,可用 Lambda 表达式。

泛型通配符:PECS

Producer Extends,Consumer Super:

代码块JAVA · 7 行收起展开
static double sum(List<? extends Number> values) {
    return values.stream().mapToDouble(Number::doubleValue).sum();
}

static void addDefaults(List<? super Integer> target) {
    target.add(0);
}
  • ? extends T:安全读取为 T,但通常不能写入具体值。
  • ? super T:可以写入 T 及其子类,读取时只能安全视为 Object。
  • 无需通配符捕获时不要过度使用通配符。

Comparator

Comparator 表示外部比较规则:

代码块JAVA · 6 行收起展开
Comparator<User> order = Comparator
        .comparingInt(User::age)
        .thenComparing(User::name)
        .reversed();

users.sort(order);

compare(a, b) 返回负数、0、正数。不要用 a - b,可能溢出。自然顺序由 Comparable#compareTo 定义,外部或多套顺序使用 Comparator。

Predicate

Predicate 接收 T 并返回 boolean:

代码块JAVA · 4 行收起展开
Predicate<String> notBlank = value -> !value.isBlank();
Predicate<String> shortText = value -> value.length() < 20;

Predicate<String> accepted = notBlank.and(shortText);

常用组合:and、or、negate。常见于 Stream.filter、removeIf。

Supplier

Supplier 无参数地产生 T,适合延迟计算、工厂和默认值:

代码块JAVA · 4 行收起展开
Supplier<List<String>> factory = ArrayList::new;
List<String> values = factory.get();

User user = optional.orElseGet(this::loadDefaultUser);

Supplier 不保证每次返回新对象,也不自动线程安全。

Consumer 与 Function

接口抽象方法用途
Consumervoid accept(T)消费值,执行副作用
Function<T, R>R apply(T)转换值
UnaryOperatorT apply(T)同类型转换
BiFunction<T, U, R>R apply(T, U)两参数计算

基本类型专用接口如 IntPredicate、IntSupplier、ToIntFunction 可减少装箱。

延伸阅读