fre*_*low 7 scala final constants compile-time-constant companion-object
class Foo {
final val pi = 3
}
Run Code Online (Sandbox Code Playgroud)
每个Foo
对象都有pi
会员吗?我应该放入pi
伴侣物体吗?
如果您担心内存占用,您可以考虑将此字段移动到伴生对象中。
是的,类的每个实例Foo
都会有该pi
值——Scala 编译器不会消除这个声明。JVM 反射允许您删除类成员上的最终修饰符,并且Unsafe
对象甚至允许修改这些修饰符。因此,Scala 编译器可以通过删除此字段来生成具有令人惊讶结果的代码,因此不应用此优化。
...
minor version: 0
major version: 50
flags: ACC_PUBLIC, ACC_SUPER
...
{
private final int pi;
flags: ACC_PRIVATE, ACC_FINAL
public final int pi();
flags: ACC_PUBLIC, ACC_FINAL
LineNumberTable:
line 243: 0
LocalVariableTable:
Start Length Slot Name Signature
...
Run Code Online (Sandbox Code Playgroud)
事实上,一些编译器转换(例如专门化)甚至可能会删除底层成员的 Final 修饰符,因此final
Scala 代码中感觉的东西可能不在final
字节码级别上。
这:
class Foo[@specialized T] {
final val pi: T = null.asInstanceOf[T]
}
Run Code Online (Sandbox Code Playgroud)
变成:
...
public final T pi;
flags: ACC_PUBLIC, ACC_FINAL
Signature: #9 // TT;
public T pi();
flags: ACC_PUBLIC
LineNumberTable:
line 243: 0
...
Run Code Online (Sandbox Code Playgroud)
上面,pi
访问器方法(即它的 getter)不再是最终的。
Oracle JVM 中的 JIT 也不会在运行时从内存中的对象表示中删除该成员 - Foo
32 位 JVM 上对象的运行时大小将为 16 字节(8 字节对象头 + 4 字节整数字段,四舍五入到 8 字节边界)。然而,JIT 可能决定将最终字段中的常量值内联到代码的某些部分中,以便消除某些字段写入。
归档时间: |
|
查看次数: |
163 次 |
最近记录: |