List [Int]和List [Integer]的类型擦除的差异

Mar*_*lic 9 java scala type-erasure scala-java-interop

为什么List[scala.Int]类型擦除,以List[Object]同时IntegerList[java.lang.Integer]似乎会保留吗?例如,javap对于

object Foo {
  def fooInt: List[scala.Int] = ???
  def fooInteger: List[java.lang.Integer] = ???
}
Run Code Online (Sandbox Code Playgroud)

输出

public scala.collection.immutable.List<java.lang.Object> fooInt();
public scala.collection.immutable.List<java.lang.Integer> fooInteger();
Run Code Online (Sandbox Code Playgroud)

我们看到的Integer是第二种情况。文档状态

Object如果泛型类型中的所有类型参数都带有边界,或者类型参数不受限制,则将其替换。

这可能是由于“ bounds”子句引起的吗?如果是这样,此界限在哪里指定?

Eug*_*ene 5

不是 Scala开发人员,请带一点盐。擦除一样的:

public static scala.collection.immutable.List<java.lang.Object> fooInt();
descriptor: ()Lscala/collection/immutable/List;

public static scala.collection.immutable.List<java.lang.Integer> fooInt();
descriptor: ()Lscala/collection/immutable/List;
Run Code Online (Sandbox Code Playgroud)

descriptor参数;这就是在呼叫站点以字节码级别引用的内容。

当您简单地进行操作时javap,它会通过查看Signature参数(进一步阅读)而变得“虚假” ,以便向您显示这个小小的冒犯性谎言。

现在考虑一下。让我们采用这种方法并将其放在类中A

static List<Integer> test() {
    return null; // or whatever that is not the point
} 
Run Code Online (Sandbox Code Playgroud)

我们进行编译,然后将.class文件共享给其他人。有人以这种形式使用它:(实际上没有的源代码A)。

public void testMe() {
    Integer x = A.test().get(0);
}
Run Code Online (Sandbox Code Playgroud)

如果您查看字节码,您将看到:

    5: invokeinterface #3,  2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
    10: checkcast     #4      // class java/lang/Integer
Run Code Online (Sandbox Code Playgroud)

必须立即提出一个问题:如何Integer 通过checkcast泛型知道(通过那)?答案是在编译时或在您的情况下Signature生成的可选A

 ()Lscala/collection/immutable/List<Ljava/lang/Object;>; //fooInt
 ()Lscala/collection/immutable/List<Ljava/lang/Integer;>; // fooInteger
Run Code Online (Sandbox Code Playgroud)

Signature信息是编译器用来通过运行时检查在callite强制执行类型安全的信息;如果该字段不存在-那将是不可能的。

我们为什么Signaturescalac产生Object(因此零呼叫者类型安全)的东西,重复的地址。我已尝试阅读该问题,但阅读起来并不容易-我会选择“我信任您”。


更多解释:在添加泛型时Signature出现java-5。在此之前,所引用的所有呼叫站点descriptorSignature改为将其替换为,这将意味着现有代码将中断;因此从来没有做过。因此Signature成为可选的,并以不同的方式使用checkcast。至少这是我强烈想要的:)