您正确理解。该5.1.7节的最后(来自https://docs.oracle.com/javase/specs/jls/se13/html/jls-5.html)说:
如果需要分配包装类之一(布尔,字节,字符,短,整数,长,浮点或双精度)的新实例,则装箱转换可能会导致OutOfMemoryError。并且没有足够的存储空间。
如果要预先生成
Byte
,就不会出现。
另一件事,仍然来自同一段:
理想情况下,将原始值装箱将始终产生相同的引用。实际上,使用现有的实现技术可能不可行。上面的规则是一种务实的折衷,要求始终将某些通用值装在无法区分的对象中。该实现可以懒惰地或急切地缓存它们。 对于其他值,该规则不允许对程序员方面的带框值的身份进行任何假设。这样可以(但不需要)共享其中一些或全部参考。
不是“证明”,但也许值得一提:
Integer
描述了拳击承诺,
13甚至是
7
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
即使实现随时间而变化,文本也一样。
Byte
没有这样的语句,尽管它也被缓存了。 7,13。两者都有缓存,但是没有一个单词(也没有关于装箱的单词)。
,
TL; DR已通过JDK 14(现已包括byte
)修复。
我认为这是一个规范错误,是多次重写的结果。
注意JLS 6 counterpart的文本:
如果要装箱的值 p 为true
,false
,一个byte
,一个char
,范围为\ u0000到\ u007f ,或介于-128和127之间的int
或short
数字,然后让 r1 和 r2 为 p。通常是 r1 == r2 。
在这里,byte
被明确提到是无条件地装箱到具有规范身份的对象。由于所有字节都在-127..128范围内,因此无需添加此类限制。
但是请注意,没有提到long
。
然后,遇到JDK-7190924,5.1.7: JLS does not mention caching of autoboxed longs
在评论中,您可以看到它是如何发生的。
亚历克斯·巴克利(Alex Buckley)在第一条评论中批评“字节是一种类型,而不是一个值”,没有考虑到“字节”可能意味着“字节范围内的所有值”,但由于他还最初假定“数字”他的意思是“文字”(而不是“数值”),他着眼于所有整数文字都是int或long的观点。
他的初稿使用术语“整数文字”并完全删除了这些类型。对其进行了稍加修改的版本使其成为Java 8 JLS:
如果要装箱的值p
是int
和-128
之间(包括第3.10.1节)的类型127
的整数文字,或者布尔文字{{ 1}}或true
(§3.10.3),或介于false
和'\u0000'
之间的字符文字(§3.10.4),然后让'\u007f'
和{{ 1}}是a
的任何两次拳击转换的结果。 b
总是这样。
因此在Java 8中,类型根本无关紧要,但保证仅限于文字。
所以这暗示着
p
由于整数字面量而求值为规范对象,其中as
a == b
可能不是,因为Byte b1 = 4;
是一个常量表达式,而不是文字。
几年后,在他的下一条评论中,他认为确实可以键入的“常量表达式”,并重新定义了该短语,并带回了“ boolean,char,short,int或long”类型,并添加了long。 ,但忘记了“字节”。
这个结果短语就是您引用的,这是Java 9以来的规范。
Byte b1 = (byte)4;
的遗漏肯定不是故意的,因为没有合理的理由忽略它,尤其是在以前的时候,所以从字面上看这将是一个重大突破。
但是,将缓存限制为编译时常量时,当JLS 6为范围内的所有值指定缓存而没有这种限制时,这已经是一个重大更改(实际上,只要实现就没有关系)通过(byte)4
,无法知道该值是否来自编译时常量。
作为旁注,Byte.valueOf(byte)
的文档明确指出:
...所有字节值都已缓存
只要since Java 7。
本文链接:https://www.f2er.com/2833317.html