将java.util.function.function转换为接口
范例 在这个(简化的)示例中,我可以使用对将java.util.function.function转换为接口,java,java-8,method-reference,Java,Java 8,Method Reference,范例 在这个(简化的)示例中,我可以使用对apply的方法引用来创建我的MyInterface-对象,但直接强制转换不起作用 @Test public void testInterfaceCast(){ Function<String, Integer> func = Integer::parseInt; MyInterface legal = func::apply; // works MyInterface illegal = func; // erro
apply
的方法引用来创建我的MyInterface
-对象,但直接强制转换不起作用
@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>{}
@测试
public void testInterfaceCast(){
函数func=Integer::parseInt;
MyInterface legal=func::apply;//有效
MyInterface非法=func;//错误
}
公共接口MyInterface扩展函数{}
第二个赋值给出编译器错误:
incompatible types: Function<String,Integer> cannot be converted to MyInterface
不兼容类型:无法将函数转换为MyInterface
问题
我可以做一些泛型魔术,以便能够将
函数
强制转换到接口吗?它不编译的原因与此代码段不编译的原因相同:
Animal animal = new Animal();
Cat x = animal; //illegal assignment
i、 你是在暗示每种动物都可以是猫。编译器没有证据表明实际的超类实例在运行时确实是cat,因此会引发错误
您必须将Integer::parseInt
分配给MyInterface
实例:
MyInterface func = Integer::parseInt;
MyInterface illegal = func;
asfunc
属于Function
类型(即MyInterface
的超级类型)
事实上,没有办法在编译时将类型为
MyInterface
的Integer::parseInt
设置为MyInterface
变量不起作用,因为func
被声明为Function
类型的变量,它不是MyInterface
的子类型
MyInterface legal=func::apply的原因代码>工程如下所示。您可能期望fun::apply
的类型也是Function
,但事实并非如此。fun::apply
的类型部分取决于编译器期望的类型。由于在赋值上下文中使用它,编译器需要类型为MyInterface
的表达式,因此在该上下文中func::apply
的类型为MyInterface
。正是由于这个原因,方法引用表达式只能出现在赋值上下文、调用上下文和强制转换上下文中(请参阅)
由于Function
不是MyInterface
的子类型,将func
强制转换为MyInterface
会引发ClassCastException
。因此,将函数
转换为MyInterface
最清晰的方法是使用方法引用,就像您已经做的那样:
MyInterface legal = func::apply;
最根本的是,尽管所有漂亮的语法表面上给出了这样一种外观,Java并没有采用结构类型;命名类型的Liskov可替换性规则一如既往地严格适用。在实际代码中,您可以调用函数。然后
,它返回函数的一些实例
,而绝对不是MyInterface的实例
。所以当你写作的时候
MyInterface legal = func::apply;
MyInterface illegal = func;
您将得到另一个对象,它是MyInterface
的实例。相比之下,当你写作的时候
MyInterface legal = func::apply;
MyInterface illegal = func;
您正试图将对函数
的现有实例的引用直接分配给非法
,这将违反Liskov可替换性,即使它在结构上与类型匹配。根本不可能有任何伎俩来回避这一问题;即使Java引入了一些新的语法糖,使它看起来像是铸造,实际的语义仍然是转换(计算到另一个实例)。出于好奇,你会怎么处理它?我有一个例子,我使用了函数。然后,它返回一个函数
,其中包含一些难看的复杂泛型,我想通过将其转换到一个接口来抽象它。铸造不会改变其类型。简单铸造在这里不起作用?只需尝试:MyInterface非法=(MyInterface)func;只是一句(可能很明显的)注释:您可以使用MyInterface legalToo=s->func.apply解决这个问题代码>…我忘了写你也不能做那个演员。你会得到这样的结果:InterfaceTest$$Lambda$1/1768883882不能转换为InterfaceTest$MyInterface java.lang.ClassCastException:InterfaceTest$$Lambda$1/1768883882不能转换为InterfaceTest$MyInterface
如果OP的MyInterface
添加了一个额外的方法(意味着它不再是一个功能接口)MyInterface legal=func::apply
会失败吗?(顺便说一句,它是否会因为函数
用@functioninterface
注释而导致编译错误?)