为什么String与Scala中的Int,Boolean,Byte ...不同?

时间:2012-11-27 08:18:21

标签: scala

因为我知道一点Java我试图在每个Scala代码中使用一些Java类型,如java.lang.Integerjava.lang.Characterjava.lang.Boolean ......等等。现在人们告诉我“不!对于Scala中的所有东西都有自己的类型,Java的东西会起作用 - 但你应该总是喜欢Scala类型和对象”。

好的,现在我知道,Scala中有Java中的所有东西。不知道为什么最好使用例如Scala Boolean而不是Java Boolean,但很好。如果我查看类型,我会看到scala.Booleanscala.Intscala.Byte ...然后我会看到字符串,但它不是scala.String,(甚至不是java.lang.String 1}} 混淆)它只是一个字符串。但我想我应该使用直接来自scala的所有内容。也许我不正确理解scala,有人可以解释一下吗?

2 个答案:

答案 0 :(得分:11)

首先,'它甚至不是java.lang.String'语句都不太正确。简单String名称来自Predef object:

中定义的类型别名
type String = java.lang.String

并且每个Scala源都会导入Predef的内部,因此您使用的是String而不是java.lang.String,但实际上它们是相同的。

java.lang.String是一个非常特殊的类,由JVM以特殊方式处理。正如@ pagoda_5b所说,它被声明为final,它不可能扩展它(这实际上是好的),因此Scala库提供了一个带有附加操作和隐式的包装器(RichString)转化String -> RichString默认可用。

但是,IntegerCharacterBoolean等情况略有不同。您可以看到,即使String被JVM专门处理,它仍然是一个平原实例为普通对象的类。从语义上讲,它与List类没有什么不同 原始类型还有另一种情况。 Java intcharboolean类型不是类,这些类型的值不是对象。但Scala是完全面向对象的语言,没有原始类型。可以在需要相应类型的地方使用java.lang.{Integer,Boolean,...},但由于装箱,这种效率非常低。
因此,Scala需要一种在面向对象的设置中呈现Java原始类型的方法,因此引入了scala.{Int,Boolean,...}类。这些类型通过Scala编译器进行特殊处理 - 当scalac遇到其中一个类时,会生成使用原语的代码。它们还会扩展AnyVal类,这会阻止您将null用作这些类型的值。这种方法解决了效率问题,在你真正需要装箱的地方留下了java.lang.{Integer,Boolean,...}类,并且还提供了使用其他主机系统原语的优雅方法(例如.NET运行时)。

答案 1 :(得分:4)

我只是在猜这里

如果查看文档,您可以看到基元的scala版本为您提供了所有预期的运算符,这些运算符可以处理数值类型,布尔类型和合理转换,而不需要像{{1包装器。

我认为这个选择是为了给出对原始类型的期望的统一和自然的访问,同时使它们java.lang与任何其他scala类型一样。

我认为Objects需要采用不同的方法,在其实施中已经java.lang.StringObject。因此,“最少痛苦的路径”是在它周围创建一个隐式的Rich包装器,以便在String上获得缺少的操作,而其余部分保持不变。

从另一个角度来看,final已经足够好了,不可变,还有什么。

值得一提的是,scala中的其他“原始”类型都有自己的Rich包装器,可以提供额外的合理操作。