Scala的基本数据类型是如何实现的?实际上,Scala以与Java同样的方式存储整数:把它当作32位的字类型。这对于有效使用JVM平台和与Java库的互操作性方面来说都很重要,。标准的操作如加法或乘法都被实现为数据类型基本运算操作。然而,当整数需要被当作(Java)对象看待的时候,Scala使用了“备份”类java.lang.Integer。如在整数上调用toString方法或者把整数赋值给Any类型的变量时,就会这么做,需要的时候,Int类型的整数能自动转换为java.lang.Integer类型的“装箱整数(boxed integer)”。
这些听上去和Java的box操作很像,实际上它们也很像,但这里有一个重要的差异,Scala使用box操作比在Java中要少的多:
// Java代码 boolean isEqual(int x,int y) { return x == y; } System.out.println(isEqual(421,421));
你当然会得到true。现在,把isEqual的参数类型变为java.lang.Integer(或Object,结果都一样):
// Java代码 boolean isEqual(Integer x, Integery) { return x == y; } System.out.println(isEqual(421,421));
你会发现你得到了false!原因是数421使用?box?操作了两次,由此参数x和y是两个不同的对象,因为在引用类型上==表示引用相等,而Integer是引用类型,所以结果是false。这是展示了Java不是纯面向对象语言的一个方面。我们能清楚观察到基本数据值类型和引用类型之间的差别。
现在在Scala里尝试同样的实验:
scala> def isEqual(x:Int,y:Int) = x == y isEqual: (x: Int, y: Int)Boolean scala> isEqual(421,421) res0: Boolean = true scala> def isEqual(x:Any,y:Any) = x == y isEqual: (x: Any, y: Any)Boolean scala> isEqual(421,421) res1: Boolean = true
Scala 的 == 设计出自动适应变量类型的操作,对值类型来说,就是自然的(数学或布尔)相等。对于引用类型,==被视为继承自Object的equals方法的别名。比如对于字符串比较:
scala> val x = "abcd".substring(2) x: String = cd scala> val y = "abcd".substring(2) y: String = cd scala> x==y res0: Boolean = true
而在Java里,,x与y的比较结果将是false。程序员在这种情况应该用equals,不过它容易被忘记。
然而,有些情况你需要使用引用相等代替用户定义的相等。例如,某些时候效率是首要因素,你想要把某些类哈希合并:hash cons然后通过引用相等比较它们的实例,为这种情况,类AnyRef定义了附加的eq方法,它不能被重载并且实现为引用相等(也就是说,它表现得就像Java里对于引用类型的==那样)。同样也有一个eq的反义词,被称为ne。例如:
scala> val x =new String("abc") x: String = abc scala> val y = new String("abc") y: String = abc scala> x == y res0: Boolean = true scala> x eq y res1: Boolean = false scala> x ne y res2: Boolean = true