24

Example

In this (simplified) example I can create my MyInterface-object by using a method reference to apply, but casting directly doesn't work.

@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>{}

The second assignment gives the compiler error:

incompatible types: Function<String,Integer> cannot be converted to MyInterface

The question

Can I do some Generics magic, to be able to cast a Function<T, R> to an Interface?

4

3 回答 3

14

原因MyInterface illegal = func;不起作用,是因为func被声明为 type 的变量Function<String,Integer>,而不是 的子类型MyInterface

起作用的原因MyInterface legal = func::apply;如下。您可能希望类型也是fun::apply如此Function<String,Integer>,但事实并非如此。的类型部分fun::apply取决于编译器期望的类型。由于您在赋值上下文中使用它,编译器需要 type 的表达式MyInterface,因此在该上下文 func::apply中是 type MyInterface。正是由于这个原因,方法引用表达式只能出现在赋值上下文、调用上下文和强制转换上下文中(参见Java 语言规范)。

由于Function<String,Integer>不是 的子类型MyInterface,因此转换func为 aMyInterface会引发ClassCastException. 因此,将 a 转换Function<String,Integer>为 a的最清晰方法MyInterface是使用方法引用,就像您已经做过的那样:

MyInterface legal = func::apply;
于 2015-08-27T07:51:11.013 回答
8

归根结底是这样一个事实,尽管所有漂亮的语法都在表面上给出了这样的外观,但 Java 并没有采用结构类型。命名类型的 Liskov 可替换性规则与以往一样严格。在您调用的实际代码Function.andThen中,它返回 的一些实例Function,并且绝对不是MyInterface. 所以当你写

MyInterface legal = func::apply;

你会得到另一个对象,它是MyInterface. 相比之下,当你写

MyInterface illegal = func;

您正在尝试直接分配对现有实例的引用 to Functionillegal这将违反 Liskov 可替换性,即使它在结构上与类型匹配。没有任何技巧可以从根本上解决这个问题。即使 Java 引入了一些新的语法糖,使它看起来像强制转换,实际的语义仍然是转换的语义(评估到另一个实例)。

于 2015-08-27T08:15:49.727 回答
2

它无法编译的原因与此代码段无法编译的原因相同:

Animal animal = new Animal();
Cat x = animal; //illegal assignment

即,您是在暗示每种动物都可以是猫。编译器没有证据表明实际的超类实例在运行时确实是一只猫,因此会引发错误。

您必须分配Integer::parseInt给一个MyInterface实例:

MyInterface func = Integer::parseInt;
MyInterface illegal = func;

as funcis of type Function<String, Integer>(即 的超类型MyInterface)。

事实是,除非将其分配给变量,否则无法在编译时Integer::parseInt生成类型。MyInterfaceMyInterface

于 2015-08-27T07:17:57.123 回答