Java奇怪的类强制转换异常

时间:2018-01-20 16:58:20

标签: java interface functional-programming classcastexception

有没有人可以帮助我理解为什么在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;
    }
}

2 个答案:

答案 0 :(得分:3)

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

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

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

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

final MagicFunction fun1 = String::trim;

实际上等同于:

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

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

答案 1 :(得分:-2)

“当然,这个方法的签名必须与方法引用的签名兼容;你不能使用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);
}