【问题标题】:Why is String different than Int,Boolean,Byte... in scala?为什么String与Scala中的Int,Boolean,Byte ...不同?
【发布时间】:2012-11-14 19:41:11
【问题描述】:

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

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

【问题讨论】:

标签: scala


【解决方案1】:

我只是猜测

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

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

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

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

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

【讨论】:

    【解决方案2】:

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

    type String = java.lang.String
    

    Predef 的内部结构在每个 Scala 源中都被导入,因此您使用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 运行时)。

    【讨论】:

      猜你喜欢
      • 2010-10-30
      • 1970-01-01
      • 2021-11-04
      • 2012-06-14
      • 2017-06-10
      • 2021-10-08
      • 1970-01-01
      • 2013-04-23
      相关资源
      最近更新 更多