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);
}
}
注意:如果你内联某些变量,那么一些非工作的例子会突然开始起作用。
我的想法很详细:
IntConsumer i = A::consume
有效,则A::consume
必须implement IntConsumer
MyConsumer i2 = A::consume
有效,则A::consume
必须implement MyConsumer
A::consume
实施,<{strong>,IntConsumer
和MyConsumer
,则应该可以投射还有另一种方式来演绎&#34;或者&#34;改变&#34;事后消费者的类型?
答案 0 :(得分:3)
之后是否有其他方式“强制”或“改变”消费者的类型?
您无法更改对象的实际类型(1)。您可以转换基元,并且可以将引用转换为适合所引用对象的另一种类型。
您可以做的是用您想要的类型包装实例。
MyConsumer mc = ((IntConsumer) A::consume)::accept;
(1)你可以破解对象头中的类指针,但这不太可能是个好主意。
答案 1 :(得分:1)
A::consume
没有固有的类型。当它出现在正在使用它或分配给功能接口类型的上下文中时,编译器将创建使用A::consume
实现的类型的对象。
完成后,您将拥有该特定功能接口类型的对象。它不是一种方法;它是一个完全正常的对象。 Java对象不能伪装成其实际类型不能实现或扩展的其他类型。
因此,一旦您拥有IntConsumer
,就无法将其投放到MyConsumer
。您可以使用它来获取方法引用,然后该方法引用可以成为 new MyConsumer
,但是该对象将始终只是IntConsumer
,仅此而已。