在Scala中使用case类与常规类相比,是否存在任何开销?它是否使用任何额外的内存,在构造中做更多,或在现场访问中做更多?或者,对于类型层次结构底部的类,它是否真的只是自由等于/ hashcode/tostring/apply/unapply/etc?
我的用例是一个值得成为案例类的类(如果所有字段相等则不可变且相等),但我处于性能至关重要的域中.
(请不要回答"不要过早担心过早优化".)
如果编译一个最小的例子:
class Ordinary(val i: Int) { }
case class Case(i: Int) { }
Run Code Online (Sandbox Code Playgroud)
你会发现普通类的字节码较小(~700 vs.~3500); 你也发现javap -c -private -v <Classname>
构造函数有一个额外的方法调用Product trait初始化器(它实际上没有做任何事情,因此应该由JIT编译器进行优化).
因此,对于重复使用一个类,它应该没有太大的区别.如果您有数千个这样的类,您可能会发现字节码增加有问题.
首先是显而易见的:由于创建了额外的方法,字节码更大.
案例类将第一个参数列表的参数保留为val
成员.如果您不需要访问除构造对象之外的参数,这将是浪费.
从Scala 2.8开始,案例类还保留后续参数部分中的参数以支持该copy
方法.这是一个实现细节,可能会有所变化.
scala> case class A(a: Int)(b: Int)
defined class A
scala> val a = A(0)(1)
a: A = A(0)
scala> a.copy()()
res9: A = A(0)
scala> :javap -private A
Compiled from "<console>"
public class A extends java.lang.Object implements scala.ScalaObject,scala.Product,scala.Serializable{
private final int a;
private final int b;
public scala.collection.Iterator productIterator();
public scala.collection.Iterator productElements();
public int a();
public A copy(int, int);
public int copy$default$2(int);
public int copy$default$1();
public int hashCode();
public java.lang.String toString();
public boolean equals(java.lang.Object);
public java.lang.String productPrefix();
public int productArity();
public java.lang.Object productElement(int);
public boolean canEqual(java.lang.Object);
private final boolean gd1$1(int);
public A(int, int);
}
Run Code Online (Sandbox Code Playgroud)