例如:
Integer i1 = 1; Integer i2 = 1; Integer i3 = new Integer(1); String s1 = "String"; String s2 = "String"; String s3 = new String ("String"); System.out.println("(i1 == i2) " + (i1 == i2)); System.out.println("(i2 == i3) " + (i2 == i3)); System.out.println("(s1 == s2) " + (s1 == s2)); System.out.println("(s2 == s3) " + (s2 == s3)); Execution result: (i1 == i2) true (i2 == i3) false (s1 == s2) true (s2 == s3) false
如您所见,基元的装箱从池中获取对象,通过字符串文字创建字符串也会从池中获取对象.这些对象实际上是同一个对象(operator ==对它们返回true).
创建包装器和字符串的其他机制不会从池中获取对象.以这些方式创建的对象实际上是不同的对象(operator ==对它们返回false).
令我困惑的是池部分使用的事实.
如果是内存问题,为什么不一直使用池?
如果它不是内存问题 – 为什么要使用它?
问题是 – 实现这种行为的原因是什么(=部分使用池)?
这个问题相当理论化,但它具有实际应用 – 它可以帮助理解如何正确使用自定义对象池,当然也可以理解Java的工作方式总是很好.
解决方法
可悲的是,它会导致你发现的一些违反直觉的行为.
结果是我们有这种奇怪的妥协. Java标准中讨论了此行为的原因. (5.7)
If the value p being Boxed is true,false,a byte,a char in the range \u0000 to \u007f,or an int or short number between -128 and 127,then let r1 and r2 be the results of any two Boxing conversions of p. It is always the case that r1 == r2.
Ideally,Boxing a given primitive value p,would always yield an identical reference. In practice,this may not be feasible using existing implementation techniques. The rules above are a pragmatic compromise. The final clause above requires that certain common values always be Boxed into indistinguishable objects. The implementation may cache these,lazily or eagerly.For other values,this formulation disallows any assumptions about the identity of the Boxed values on the programmer’s part. This would allow (but not require) sharing of some or all of these references.
This ensures that in most common cases,the behavior will be the desired one,without imposing an undue performance penalty,especially on small devices. Less memory-limited implementations might,for example,cache all characters and shorts,as well as integers and longs in the range of -32K – +32K.
TL;博士
让它完美地工作是不可能的,而且根本没有让它工作太奇怪了.所以我们让它在“大多数时间”工作.