首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >了解编译的Scala文件中的类型

了解编译的Scala文件中的类型
EN

Stack Overflow用户
提问于 2017-01-08 02:19:17
回答 1查看 79关注 0票数 0

给定:

代码语言:javascript
复制
$cat build.sbt
scalaVersion := "2.12.1"

$cat src/main/scala/net/X.scala
package net 

trait Foo 
object X {

    val a: Int with Foo = 42.asInstanceOf[Int with Foo]

    println(a + a)

}

在通过sbt compile编译之后,我对输出的class文件进行了javap

代码语言:javascript
复制
$javap target/scala-2.12/classes/net/X\$.class 
Compiled from "X.scala"
public final class net.X$ {
  public static net.X$ MODULE$;
  public static {};
  public int a();
}

$javap target/scala-2.12/classes/net/X.class 
Compiled from "X.scala"
public final class net.X {
  public static int a();
}

为什么a的类型是int

我在object X中指定了一种Int with Foo类型。

EN

回答 1

Stack Overflow用户

发布于 2017-01-08 03:18:37

这就是Scala中所有交叉点类型被编译成JVM字节码的方式。JVM无法表示像Int with Foo这样的东西,因此编译器将类型擦除为第一个“简单”类型:本例中的Int。这意味着,如果像使用Foo一样使用值a,编译器必须在字节码中插入强制转换。

看看下面的REPL会话:

代码语言:javascript
复制
Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_111).
Type in expressions for evaluation. Or try :help.

scala> trait Foo { def foo = "foo" }
defined trait Foo

scala> trait Bar { def bar = "bar" }
defined trait Bar

scala> class FooBar extends Foo with Bar
defined class FooBar

scala> class Test { val foobar: Foo with Bar = new FooBar }
defined class Test

scala> object Main {
     |   def main(): Unit = {
     |     val test = new Test().foobar
     |     println(test.foo)
     |     println(test.bar)
     |   }
     | }
defined object Main

scala> :javap -p -filter Test
Compiled from "<console>"
public class Test {
  private final Foo foobar;
  public Foo foobar();
  public Test();
}

scala> :javap -c -p -filter Main
Compiled from "<console>"
  ...
  public void main();
    Code:
      ...
      15: invokeinterface #62,  1           // InterfaceMethod Foo.foo:()Ljava/lang/String;
      ...
      27: checkcast     #23                 // class Bar
      30: invokeinterface #69,  1           // InterfaceMethod Bar.bar:()Ljava/lang/String;
      ...

Int with Foo实际上是一个特例。Int是最终的类型,而Foo是一个特征。显然,与特征相比,编译器更喜欢final类型和类。因此,在Foo with Bar中,Foo是一个特征,Bar是一个类,类型仍然被擦除为Bar而不是Foo

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41524869

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档