package p;
public class X {
private int x;
public X supp(Function<Integer, X> f){
return f.apply( 1);
}
}
supp
的字节码:
public supp(Ljava/util/function/Function;)Lp/X;
L0
LINENUMBER 24 L0
ALOAD 1
ICONST_1
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
INVOKEINTERFACE java/util/function/Function.apply (Ljava/lang/Object;)Ljava/lang/Object;
CHECKCAST p/X
ARETURN
L1
LOCALVARIABLE this Lp/X; L0 L1 0
LOCALVARIABLE f Ljava/util/function/Function; L0 L1 1
字节码的第一个版本对我来说有点古怪,特别是CHECKCAST p/X
。
我不明白。我知道运行时存在泛型类型擦除(实际上,f.apply(1)
返回Object
而不是X
,而supp
返回X
。所以这个检查看似java
(解释器)的转换会尝试确保f.apply(1)
实际上返回X
。
但是,为什么有必要呢?看起来java
不信任javac
。基本上,在编译时基于类型检查的Java中没有真正的泛型。
答案 0 :(得分:3)
CHECKCAST
是必需的,因为由于类型擦除,在运行时没有关于函数返回类型的信息。
例如,没有什么可以阻止您将原始Function
传递给supp
方法:
X x = new X();
Function f = o -> new Y();
x.supp(f);
此代码编译(带有未经检查的赋值警告),但在运行时抛出ClassCastException
。