一个例子胜过千言万语:
class A { def foo: Any = new Object }
class B extends A {
override def foo: AnyVal = 42
}
在Java中,甚至不允许签名@Override public int foo()
,foo
中重写的方法B
只能返回包装器整数类型(@Override java.lang.Integer foo()
)。
Scala是否能够避免在上面重写的AnyVal
方法中装箱/取消装箱def foo: AnyVal
值?
答案 0 :(得分:4)
不,它没有。 Scala必须坚持发出正确的字节码:
λ scalac -Xprint:jvm Bar.scala
[[syntax trees at end of jvm]] // Bar.scala
package yuval.tests {
class A extends Object {
def foo(): Object = new Object();
def <init>(): yuval.tests.A = {
A.super.<init>();
()
}
};
class B extends yuval.tests.A {
override def foo(): Object = scala.Int.box(42);
def <init>(): yuval.tests.B = {
B.super.<init>();
()
}
}
}
您可以看到虽然Scala中允许AnyVal
,但发出的foo
的实际方法签名是Object
而不是AnyVal
和Int
盒装。
答案 1 :(得分:0)
Yuval的答案可以概括为:AnyVal
的删除是Object
(你可以在REPL中输入classOf[AnyVal]
看到这一点),所以每当你AnyVal
进入时Scala,你可以在字节码中得到Object
。
E.g。如果您将A
更改为
class A { def foo: AnyVal = 0 }
它仍然是Object
。
也许有某些情况下使用AnyVal
本身会避免拳击,但我会感到惊讶。它的创建非常适合编译器的方便,稍后再次使用(value classes),但它在用户代码中很少有用(定义值类除外)。