要创建一个新的Integer对象,该对象在Java 1中保存值,以下其中一项是正确的,并且以下方法的区别到底是什么,因为所有方法都将打印该值?
方法1:
Integer p = new Integer(1);
方法2:
Integer p = 1;
方法3:
Integer p = new Integer("1");
使用方法三,我得到以下警告:
Note: HelloWorld.java uses or overrides a deprecated API. Note: Recompile with -Xlint:deprecation for details
您跳过了预期的解决方案:
Integer p = Integer.valueOf(1);
此模式称为Factory方法模式。有人可能会问这种方法有什么好处。幸运的是,classInteger的实现是开源的,因此让我们看一下:
Integer
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
似乎存在某种Integer-value缓存。如果请求一个Integer具有缓存范围内的值的Java,则Java不会创建新对象,而是返回先前创建的对象。这Integer是可行的,因为s是不可变的。甚至可以使用system属性来控制高速缓存上限java.lang.Integer.IntegerCache.high=...。
java.lang.Integer.IntegerCache.high=...
为什么其他两种创建Integer警告的方法也会产生警告?因为它们已被Java 9弃用。
Integer#Integer(int value):
Integer#Integer(int value)
不推荐使用 。很少适合使用此构造函数。valueOf(int)通常,静态工厂是一个更好的选择,因为它可能会产生明显更好的空间和时间性能。[…]
valueOf(int)
Integer#Integer(String s):
Integer#Integer(String s)
不推荐使用 。很少适合使用此构造函数。使用parseInt(String)一个字符串转换为int原始的,或使用valueOf(String)一个字符串转换为一个Integer对象。[…]
parseInt(String)
int
valueOf(String)
仅出于完整性考虑,以下是用于Integer.valueOf(int i):
Integer.valueOf(int i)
返回Integer表示指定int值的实例。如果Integer不需要新实例,则通常应优先于构造方法使用Integer(int)此方法,因为通过缓存经常请求的值,此方法可能会产生明显更好的空间和时间性能。此方法将总是在范围内的缓存值-128到127,包容性,并可以外接高速缓存的这个范围以外的值。
Integer(int)
-128
127
编辑1:感谢@VGR提到
等同于
但是,这仅适用于和int之间的-128-值127。该行为在JLS§5.1.7中定义:
[…]如果该值p被装箱是评价类型的常量表达式(§15.28)的结果boolean,char,short,int,或long,其结果是true,false在的范围内的字符'\u0000',以'\u007f'包容,或在范围内的整数-128以127包容性的,然后让a和b是任意两个装箱转换的结果p。总是这样的a == b。
p
boolean
char
short
long
true
false
'\u0000'
'\u007f'
a
b
a == b
虽然不在JLS中,但javac我正在使用(9.0.4)的版本确实将装箱压缩到了AdamRosenfieldInteger.valueOf(...);在此答案中所示的位置。
javac
9.0.4
Integer.valueOf(...);
Integer p = Integer.valueOf(1);建议使用方法4 。JavaDoc说:
Integer p = Integer.valueOf(1)
返回表示指定int值的Integer实例。如果不需要新的Integer实例,则通常应优先于构造方法Integer(int)使用此方法,因为此方法通过缓存经常请求的值可能会产生明显更好的空间和时间性能。此方法将始终缓存-128至127(包括)范围内的值,并且可能缓存该范围之外的其他值。