Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将java.util.function.function转换为接口_Java_Java 8_Method Reference - Fatal编程技术网

将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;
as
func
属于
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
注释而导致编译错误?)