因为我知道一点Java我试图在每个Scala代码中使用一些Java类型,如java.lang.Integer
,java.lang.Character
,java.lang.Boolean
......等等。现在人们告诉我“不!对于Scala中的所有东西都有自己的类型,Java的东西会起作用 - 但你应该总是喜欢Scala类型和对象”。
好的,现在我知道,Scala中有Java中的所有东西。不知道为什么最好使用例如Scala Boolean而不是Java Boolean,但很好。如果我查看类型,我会看到scala.Boolean
,scala.Int
,scala.Byte
...然后我会看到字符串,但它不是scala.String
,(甚至不是java.lang.String
1}} 混淆)它只是一个字符串。但我想我应该使用直接来自scala的所有内容。也许我不正确理解scala,有人可以解释一下吗?
答案 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
默认可用。
但是,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运行时)。
答案 1 :(得分:4)
我只是在猜这里
如果查看文档,您可以看到基元的scala版本为您提供了所有预期的运算符,这些运算符可以处理数值类型,布尔类型和合理转换,而不需要像{{1包装器。
我认为这个选择是为了给出对原始类型的期望的统一和自然的访问,同时使它们java.lang
与任何其他scala类型一样。
我认为Objects
需要采用不同的方法,在其实施中已经java.lang.String
,Object
。因此,“最少痛苦的路径”是在它周围创建一个隐式的Rich包装器,以便在String上获得缺少的操作,而其余部分保持不变。
从另一个角度来看,final
已经足够好了,不可变,还有什么。
值得一提的是,scala中的其他“原始”类型都有自己的Rich包装器,可以提供额外的合理操作。