6

因为我对 Java 有一点了解,所以我试图在每个 Scala 代码中使用一些 Java 类型,比如java.lang.Integer, java.lang.Character, java.lang.Boolean... 等等。现在人们告诉我“不!Scala 中的所有东西都有自己的类型,Java 的东西可以工作——但你应该总是更喜欢 Scala 类型和对象”。

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

4

2 回答 2

12

首先,“好吧,它甚至不是 java.lang.String”的说法并不完全正确。普通String名称来自Predef对象中定义的类型别名:

type String = java.lang.String

和 insidesPredef在每个 Scala 源中都导入,因此您使用String而不是 full java.lang.String,但实际上它们是相同的。

java.lang.String是JVM以特殊方式对待的非常特殊的类。正如@pagoda_5b 所说,它被声明为final,无法扩展它(这实际上很好),因此Scala 库提供了一个包装器 ( RichString),其中包含额外的操作和String -> RichString默认情况下可用的隐式转换。

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

于 2012-11-27T11:03:47.293 回答
4

我只是在这里猜测

如果您查看文档,您可以看到原语的 scala 版本为您提供了适用于数字类型或布尔类型的所有预期运算符,以及合理的转换,而无需像java.lang包装器那样使用装箱拆箱。

我认为做出这个选择是为了统一和自然地访问原始类型的预期,同时使它们Objects与任何其他 scala 类型一样。

我想这java.lang.String需要一种不同的方法,Object已经是一种方法,并且final在其实施中。因此,“痛苦最小的路径”是围绕它创建一个隐式 Rich 包装器,以获取对 String 的缺失操作,同时保持其余部分不变。

换个角度看,java.lang.String已经足够好了,是不可变的,还有什么。

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

于 2012-11-27T09:27:28.820 回答