scala - 为什么将值类数组编译为对象数组?
问题描述
据我了解,如果您创建一个值类的数组,您实际上是在创建一个对象数组而不是包装的原语。这背后的原因是什么?
资源:
class Wrapper(val underlying: Int) extends AnyVal
class Main {
val i: Int = 1
val w: Wrapper = new Wrapper(1)
val wrappers = Array[Wrapper](new Wrapper(1), new Wrapper(2))
val ints = Array[Int](1, 2)
}
javap输出:
public class Main {
public int i();
public int w();
public Wrapper[] wrappers(); // <----why can't this be int[] as well
public int[] ints();
public Main();
}
解决方案
值类的限制之一是它x.isInstanceOf[ValueClass]
应该仍然可以正常工作。正确的意思是:透明地,程序员不必知道值何时可能被装箱或不装箱。
如果在运行时将Array[Meter]
an 表示为 an Array[Int]
,则以下代码将无法按预期工作,因为数组中的整数实际上是米的信息丢失了。
class Meter(val value: Int) extends AnyVal
def centimeters[A](as: Array[A]) = as.collect{ case m: Meter => m.value * 100 }
请注意,如果您有,val m = new Meter(42); m.isInstanceOf[Meter]
那么编译器知道这m
是 aMeter
即使它是Int
在运行时,他可以内联isInstanceOf
对true
.
另请注意,这不适用于数组。如果您要按需将数组中的值装箱,则必须创建一个新数组,这对程序员来说是不透明的,因为数组是可变的并且使用引用相等。对于大型阵列的性能来说,这也将是一场灾难。
推荐阅读
- c++ - 在对向量中,找到第一个值等于 X 的对并返回第二个值,或者返回 Y
- python - 在python中读取spss文件的问题
- python - 权限错误:[Errno 1] 操作不允许
- c# - 验证用户输入是字母表中的一个字母
- javascript - Typescript 库:隐藏内部导出
- c# - 防止用户直接调用action方法
- java - 为 Swing 应用程序选择哪个 LayoutManager?
- python - 如何并排组合一个numpy数组和一个熊猫系列并返回匹配的行数
- python - Choropleth 地图 geopandas
- typescript - 如何使用 babel 7 和 TypeScript 3.7 运行 mocha 6?