Java 奇怪 class 转换异常

Java strange class cast exception

谁能帮我理解为什么在 1 种情况下我没有 ClassCastException?至少 String::trim 不是 MagicFunction。

public class Main {

    @FunctionalInterface
    interface MagicFunction extends Function<String, String> {
    }

    public static void main(String[] args) throws IOException {
        // 1. OK
        final MagicFunction fun1 = String::trim;

        // 2. java.lang.ClassCastException
        Function<String, String> trim = String::trim;
        final MagicFunction fun2 = (MagicFunction) trim;
    }
}

所以,method references(像String::trim)有点奇怪;与 Java 中的大多数表达式不同,它们实际上没有自己的类型。像这样:

System.out.println((String::trim).getClass());

甚至不会编译,因为它没有给编译器足够的信息来说明 String::trim 应该是什么类型。

相反,每个方法引用的类型必须从周围的上下文中推断,例如通过作为赋值语句的右侧(使用左侧变量的类型)或直接传递给方法(使用方法参数的类型)。然后,编译器会为您生成一个 class,它使用相关方法实现了适当的类型。像这样:

final MagicFunction fun1 = String::trim;

实际上等同于:

final MagicFunction fun1 = new MagicFunction() {
    public String apply(final String s) {
        return s.trim();
    }
};

请注意,这仅适用于特定类型,称为 "functional interface" 类型。 detailed rules 有点复杂,但基本思想是它必须是一个只有一个抽象方法的接口类型。方法参考提供了该方法的实现。 (当然,此方法的签名必须与方法引用的签名兼容;您不能使用 String::trim 来实现 Function<Integer, Integer>。)

“当然,此方法的签名必须与方法引用的签名兼容;您不能使用 String::trim 来实现 Function。” - 是的你可以。这是一个例子

String g = "testString";
testMethod(String::trim, g);


public static <T, R> void testMethod(Function<T, R> func, T t) {
    func.apply(t);
}