[英]Cast java.util.function.Function to Interface
例
在此(简化)的例子,我可以创造我的MyInterface
使用方法参照-object apply
,而是直接铸造不起作用。
@Test
public void testInterfaceCast(){
Function<String, Integer> func = Integer::parseInt;
MyInterface legal = func::apply; // works
MyInterface illegal = func; // error
}
public interface MyInterface extends Function<String, Integer>{}
第二个赋值给出了编译器错误:
incompatible types: Function<String,Integer> cannot be converted to MyInterface
这个问题
我可以做一些泛型魔法,能够将Function<T, R>
转换为接口吗?
MyInterface illegal = func;
的原因MyInterface illegal = func;
不起作用,是因为func
被声明为Function<String,Integer>
类型的变量,它不是MyInterface
的子类型。
MyInterface legal = func::apply;
作品如下。 你可能期望fun::apply
的类型也是Function<String,Integer>
,但事实并非如此。 fun::apply
的类型部分取决于编译器期望的类型。 由于您在赋值上下文中使用它,因此编译器需要一个类型为MyInterface
,因此在该上下文中, func::apply
的类型为MyInterface
。 正是由于这个原因,方法引用表达式只能出现在赋值上下文,调用上下文和转换上下文中(参见Java语言规范 )。
由于Function<String,Integer>
不是MyInterface
的子类型, MyInterface
将func
强制转换为MyInterface
会引发ClassCastException
。 因此,将Function<String,Integer>
转换为MyInterface
方法是使用方法引用,就像您已经做过的那样:
MyInterface legal = func::apply;
最重要的是,尽管所有漂亮的语法都表面上看起来如此,但Java并没有采用结构类型; Liskov 命名类型的可替代性规则与以往一样严格。 在你的现实代码中,你调用Function.andThen
,它返回一些Function
的实例,绝对不是MyInterface
的实例。 所以当你写作
MyInterface legal = func::apply;
你会得到另一个对象,它是MyInterface
一个实例。 相比之下,当你写作
MyInterface illegal = func;
您试图将对现有Function
的引用直接分配给illegal
,这会违反Liskov可替代性,即使它在结构上与类型匹配。 没有任何技巧可以从根本上解决这个问题; 即使Java引入了一些新的语法糖,它会使它看起来像转换,实际的语义仍然是转换 (评估到另一个实例)。
由于此代码段无法编译,因此无法编译:
Animal animal = new Animal();
Cat x = animal; //illegal assignment
即你暗示每只动物都可以成为一只猫。 编译器没有证据表明实际的超类实例在运行时确实是一只猫 ,因此会引发错误。
您必须将Integer::parseInt
分配给MyInterface
实例:
MyInterface func = Integer::parseInt;
MyInterface illegal = func;
因为func
的类型是Function<String, Integer>
(即MyInterface
的超类型)。
事实是, 除非将它分配给MyInterface
变量, 否则 MyInterface
在编译时生成类型为MyInterface
Integer::parseInt
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.