Java方法参考中类型参数的使用

Zz'Rot:

在Java Precisely 3rd Ed。中,有以下代码片段:

BiConsumer<Double[], Comparator<Double>> arraySorter = Arrays::<Double>sort;

但是,我注意到,即使在<Double>after之后::,方法引用仍然有效(由于的类型参数而有意义BiConsumer)。

不过,我很困惑是否存在这样的情况下,::<T>有必要在方法的参考,如果是这样,一个例子将是非常有益。

AJNeufeld:

我认为Java 10的局部变量类型推断(var name = ...;)将解决这个难题。代替目标变量类型提供方法引用的类型,右侧需要完全指定类型,这需要::<T>在方法引用上使用类型参数()。

首先想到了大门...

var arraySorter = Arrays::<Double>sort;

...但是方法引用本身并没有定义类型。它们需要由编译器转换为功能对象,并且即使存在正好一个类型,编译器也不会搜索寻找适当类型的已知功能接口。


接下来的想法是使用方法引用作为方法的参数,该方法基于该方法的参数返回类型。

class Spy {
    static <T> Function<T,T> f2(Function<T,T> f) {
        return f.andThen(f);
    }

    static <T> T identity(T t) {
        return t;
    }
}

使用此方法,我们可以创建传递给方法的方法引用的局部变量:

Function<Double,Double> double_identity = f2(Spy::<Double>identity);

如预期的那样,我们可以删除 ::<Double>

Function<Double,Double> double_identity = f2(Spy::identity);

出乎意料的是,使用局部变量类型推断就可以了。

var double_identity = f2(Spy::identity);             // Infers <Object>!
Object obj = null;
double_identity.apply(obj); 

但是,当使用方法引用类型覆盖它时,真正的惊喜就来了。

var double_identity = f2(Spy::<Double>identity);     // Error: Double != Object

经过一番战斗,我弄清楚了原因。我们必须将类型应用于f2方法本身:

var double_identity = Spy.<Double>f2(Spy::identity); // Works.

回想起来,这是有道理的。变量的类型通常为外部函数提供上下文。通过将结果分配给Function<Double,Double>变量,编译器可以推断的类型f2(...),然后将该类型传递给参数。var name = ...没有显式类型的情况下,只有一个可用的类型是Object,因此编译器会进行推断Spy.<Object>f2(...),然后确定参数类型必须为Function<Object,Object>

不幸的是,它似乎没有从内到外进行解析,因此Spy::<Double>identity不会导致将函数推断为Spy.<Double>f2(...),将变量推断Function<Double,Double>也许Java 11?可能会损坏太多,无法正常工作。

但是,它确实终止了我var name = ...;为解决OP难题而进行的滥用尝试


非常感谢@Eugene批评了我在Java 10发行之前的尝试。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章