值类型的装箱问题

之前在ATA上讨论过的一个unit类型为何会被装箱的问题:http://www.atatech.org/qa/detail/11811?group_id=51
外网可能无法访问,转述一下。

先通过scala-user邮件列表的一个例子看看:

[scala toolbar=”false” light=”true”]
class Y(val i: Int) extends AnyVal

object X {
def main(args: Array[String]) {
val y = new Y(3) // ok
println(y) // oops, should be y.i
}
}
[/scala]

通过 scalac -print A.scala 来看编译的输出

[scala toolbar=”false” light=”true”]
def main(args: Array[String]): Unit = {
// 这里并没有用 new Y(3) ,没有在堆上分配对象
val y: Int = 3;
// 这里做了装箱,因为println接受的参数类型是Any
scala.this.Predef.println(new Y(y))
};
[/scala]

已经有人实现了一个sbt的插件,用来检查编译时box,给出警告信息的:https://github.com/retronym/boxer

分析一下为什么 Any类型的变量在被赋值一个Int值时会发生boxing,归根到底,是因为Any/AnyVal 类型被翻译为java时是使用的 Object 这个引用类型

[scala toolbar=”false” light=”true”]
scala -Xprint:jvm -e ‘val a:Any=100’

final class Main$$anon$1 extends Object {
private[this] val a: Object = _; //Any/AnyVal都被转为Object
<stable> <accessor> private def a(): Object = Main$$anon$1.this.a;
def <init>(): anonymous class anon$1 = {
Main$$anon$1.super.<init>();
Main$$anon$1.this.a = scala.Int.box(100); //需要boxing
()
}
}
[/scala]

而 Int,Float, Unit这些类型被翻译为java代码时,就是对应的java基本类型的int, float, void

[scala toolbar=”false” light=”true”]
scala -Xprint:jvm -e ‘val b:Int=100’

final class Main$$anon$1 extends Object {
private[this] val b: Int = _; // 就是 java里的int类型,
<stable> <accessor> private def b(): Int = Main$$anon$1.this.b;
def <init>(): anonymous class anon$1 = {
Main$$anon$1.super.<init>();
Main$$anon$1.this.b = 100; //不需要boxing
()
}
}
[/scala]

发表评论

电子邮件地址不会被公开。 必填项已用*标注