如何更改函数引用的类型?

时间:2016-03-08 11:44:06

标签: java functional-programming

Java8允许我使用方法声明作为我的任何接口的实现,只要它只包含一个方法。

但是一旦定义,就无法更改类型。

我的代码:

import java.util.function.IntConsumer;

public class A {

    interface MyConsumer {
        void doSomething(int i);
    }

    public static void main(String[] args) {
        IntConsumer i = A::consume;
        MyConsumer i2 = A::consume;

        IntConsumer i3 = (IntConsumer) i2; // ClassCastException
        MyConsumer i4 = (MyConsumer) i; // ClassCastException

        IntConsumer i5 = i2; // does not compile
        MyConsumer i6 = i; // does not compile

        IntConsumer i7 = i2::doSomething; // workaround, as suggested by @Eran http://stackoverflow.com/a/35846001/476791
        MyConsumer i8 = i::accept;

        Object i9 = A::consume; // does not compile
        Object i10 = (IntConsumer) A::consume; // works
        Object i11 = (MyConsumer) A::consume; // works
        Object i12 = (MyConsumer) (IntConsumer) A::consume; // does not work
    }

    static void consume(int i) {
        System.out.println(i);
    }
}

注意:如果你内联某些变量,那么一些非工作的例子会突然开始起作用。

我的想法很详细:

  1. 如果IntConsumer i = A::consume有效,则A::consume必须implement IntConsumer
  2. 如果MyConsumer i2 = A::consume有效,则A::consume必须implement MyConsumer
  3. 如果A::consume实施,<{strong>,IntConsumerMyConsumer,则应该可以投射
  4. 还有另一种方式来演绎&#34;或者&#34;改变&#34;事后消费者的类型?

2 个答案:

答案 0 :(得分:3)

  

之后是否有其他方式“强制”或“改变”消费者的类型?

您无法更改对象的实际类型(1)。您可以转换基元,并且可以将引用转换为适合所引用对象的另一种类型。

您可以做的是用您想要的类型包装实例。

MyConsumer mc = ((IntConsumer) A::consume)::accept;

(1)你可以破解对象头中的类指针,但这不太可能是个好主意。

答案 1 :(得分:1)

A::consume没有固有的类型。当它出现在正在使用它或分配给功能接口类型的上下文中时,编译器将创建使用A::consume实现的类型的对象。

完成后,您将拥有该特定功能接口类型的对象。它不是一种方法;它是一个完全正常的对象。 Java对象不能伪装成其实际类型不能实现或扩展的其他类型。

因此,一旦您拥有IntConsumer,就无法将其投放到MyConsumer。您可以使用它来获取方法引用,然后该方法引用可以成为 new MyConsumer,但是该对象将始终只是IntConsumer,仅此而已。