Java 原始包装类(整数、双精度等)和字符串是否可以近似为基于值的类?

Java 原始包装类(整数、双精度等)和字符串是否可以近似为基于值的类?,java,java-8,Java,Java 8,Java在Java8中引入了基于值的类,并且只标记了少量Java.Util(可选)和Java.time类 定义了基于值的类的标准 这些标准中的大多数(除了在身份敏感操作中使用它们的严格指导以及它们不应该具有可访问的构造函数这一事实)似乎适合于Integer、Double等原始包装类(以及类似的不可变类,如String)。我知道从技术上讲,开发人员可能已经将这些类用于基于身份的操作(尽管他们不应该这样做),因此现在将它们标记为基于值的可能会导致向后兼容性问题。但除此之外,还有什么其他原因导致这些包

Java在Java8中引入了
基于值的
类,并且只标记了少量Java.Util(可选)和Java.time类

定义了基于值的类的标准

这些标准中的大多数(除了在身份敏感操作中使用它们的严格指导以及它们不应该具有可访问的构造函数这一事实)似乎适合于Integer、Double等原始包装类(以及类似的不可变类,如String)。我知道从技术上讲,开发人员可能已经将这些类用于基于身份的操作(尽管他们不应该这样做),因此现在将它们标记为基于值的可能会导致向后兼容性问题。但除此之外,还有什么其他原因导致这些包装类在概念上不是基于值的呢

我倾向于认为它们是基于价值的


当您定义
整数myInt=5
时,您真正感兴趣的是值5,而不是包含该值的引用(至少对于我能想到的大多数用例)。同样,当你说
String myStr=“hello world”
时,你真正感兴趣的是值文字“hello world”,而不是它的引用。

基本上,你提到了最重要的原因,为什么将这些类改型为基于值是不可行的:向后兼容性

您可能已经注意到,在Java9中,基本包装类型的构造函数已经被弃用,这将是朝着这个方向迈出的一步。尽管如此,使用对身份敏感的操作只是不被鼓励,而不是被禁止,因此不能在此基础上进行破坏兼容性的更改。但潜在的破坏身份敏感操作,将是唯一可能使基于价值的类获得后续实际优势的东西

对于像
String
biginger
BigDecimal
这样的类,JDK开发人员甚至不敢拒绝使用构造函数,很可能是因为这会造成太大的干扰。对于某些构造函数,甚至没有等效的工厂方法

但不仅仅是公共构造函数

请参阅
valueOf
方法的文档,示例性:

此方法将始终缓存范围为-128到127(含)的值

因此,当使用工厂方法时,在某些情况下仍然会获得指定的标识行为

这让我们想到:

如果被装箱的值p是计算类型为
布尔
字节
字符
int
,或
,且结果为
,则为
'\u0000'
'\u007f'
范围内的字符,或者一个介于
-128
127
之间的整数,然后将
a
b
作为
p
任意两次装箱转换的结果。通常情况下,
a==b

因此,即使是该语言也指定了某些身份敏感操作的行为

请注意,规范试图不命名编译代码将在实践中使用的
valueOf
方法,而是制定自己的规则(形式上仅适用于编译时常量),这并没有真正起作用。作为文件,规范的这一部分经历了几次重写,因此,当任何人按照字面理解措辞时,保证会随着时间的推移而改变

其他的保证已经深深地烙进了开发者的脑海:

:
String
类型的常量表达式始终是“interned”,以便使用
String.intern
方法共享唯一实例

这是关于对象身份的保证,是不可能拒绝的

有趣的是,各国:

字符串对象是新创建的(),除非表达式是常量表达式()

目前还不清楚这种严格的措辞是否是有意的,但如前所述,它指出对于非常量字符串连接,它必须生成一个具有不同标识的新对象。还有一种开发人员不应该依赖的特定行为

因此,如果有人要设计一种没有遗产的新语言,那么首先将这些类型设计为值类型没有什么错。设计者必须避免将所有这些保证放在过去被认为是一个好主意的规范中。

< P>基于价值的类的目的是为真正的价值类型奠定基础,即类似于C的代码>结构> <代码> >

值类型不是堆上的对象,因此它们不是使用
new
创建的,也不是从
Object
派生的,因此它们没有对象监视器(锁)

这就是为什么以下两条规则是基于价值的定义的一部分:

  • 不要使用对身份敏感的操作,例如实例之间的引用相等(=),实例的身份哈希代码,或实例的内在锁上的同步

  • 没有可访问的构造函数,而是通过工厂方法进行实例化,工厂方法不承诺返回实例的标识

正如Brian Goetz于2015年1月6日所评论的:

可选
是新的,免责声明在第一天到达<另一方面,code>Integer
可能被无望地污染了,我确信,如果
Integer
不再可锁定(尽管我们可能认为这是一种做法),它会破坏大量重要的代码



参考资料:

在列出的资格中:没有可访问的构造函数。是的,那是