Scala 多态类型中基元类型的类型信息

Scala 多态类型中基元类型的类型信息,scala,polymorphism,jvm-bytecode,Scala,Polymorphism,Jvm Bytecode,鉴于以下目标: object Foo { val bar: List[Int] = List(1, 2, 3) } 当我们将此文件编译为JVM字节码时,由于类型擦除以及Java不支持将基元类型作为泛型类型的参数,这将被转换为列表 我们可以通过使用javap-l编译和检查.class来了解这一点: public static com.yuvalitzchakov.github.Foo$ MODULE$; descriptor: Lcom/yuvalitzchakov/github/Foo

鉴于以下目标:

object Foo {
  val bar: List[Int] = List(1, 2, 3)
}
当我们将此文件编译为JVM字节码时,由于类型擦除以及Java不支持将基元类型作为泛型类型的参数,这将被转换为
列表

我们可以通过使用
javap-l
编译和检查
.class
来了解这一点:

public static com.yuvalitzchakov.github.Foo$ MODULE$;
  descriptor: Lcom/yuvalitzchakov/github/Foo$;
  flags: ACC_PUBLIC, ACC_STATIC

public scala.collection.immutable.List<java.lang.Object> bar();
  descriptor: ()Lscala/collection/immutable/List;
  flags: ACC_PUBLIC
  Code:
    stack=1, locals=1, args_size=1
        0: aload_0
        1: getfield      #19                 // Field bar:Lscala/collection/immutable/List;
        4: areturn
      LineNumberTable:
        line 4: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/yuvalitzchakov/github/Foo$;
    Signature: #17                          // ()Lscala/collection/immutable/List<Ljava/lang/Object;>;
publicstaticcom.yuvalitzchakov.github.Foo$MODULE$;
描述符:Lcom/yuvalitzchakov/github/Foo$;
标志:ACC_公共,ACC_静态
public scala.collection.immutable.List bar();
描述符:()Lscala/collection/immutable/List;
旗帜:ACC_PUBLIC
代码:
堆栈=1,局部变量=1,参数大小=1
0:aload_0
1:getfield#19//字段栏:Lscala/collection/immutable/List;
4:轮到你了
LineNumberTable:
第4行:0
LocalVariableTable:
起始长度插槽名称签名
0 5 0本Lcom/yuvalitzchakov/github/Foo$;
签名:#17/()Lscala/collection/immutable/List;
但是,如果我们将其编译成JAR文件,然后将其作为另一个Scala项目中的依赖项,并尝试将
Foo.bar
设置为不同的值,Scala编译器将推断该类型为
List[Int]
,而不是
List[Object]

在浏览了
.class
文件之后,我找不到有关类型参数的信息,这将允许Scala编译器成功地将其推断为
列表[Int]


此元数据存储在何处,以便我们可以将此类型称为实际的
List[Int]
而不是
List[Object]

JVM类文件格式允许编译器将自定义属性放入类文件中,请参阅。除其他外,Scala编译器将有关名称的Scala签名的信息放入它生成的类文件中,以便在以后的编译器运行时,它可以再次读取这些信息。Java虚拟机需要忽略它们不理解的属性,所以在运行时这并没有什么区别

我没有找到注释的二进制格式规范,但如果您想深入了解实现,我发现:

  • 中类型的序列化
  • 中类型的反序列化
对于Scala3.0,甚至计划使用新的“tasty”格式将完整的抽象语法树(包括类型检查器生成的信息)存储在类文件中。Tasty代表“类型化抽象语法树”。基本思想是在类型检查阶段之后序列化抽象语法树,并将其放入类文件中。随后的编译器运行可以加载依赖项的完整抽象语法。这不仅允许类型检查,还允许跨模块内联和其他全局优化

Tasty计划成为Scala抽象语法树的通用交换格式,也用于编译器和集成开发环境之间的通信以及元编程


如果您想深入研究实现,可能中的文件是一个很好的开始。

我假设Scala的类型系统中有一些特定于Scala的属性,
javap
不理解,因此不会打印。@Holger很有意思,也许看看scalac的JVM阶段会有所帮助。