比较Java中的Character,Integer和类似类型:使用equals还是==?

我想确定Java中的一些东西:如果我有一个字符或一个整数或一个Long以及那些东西,我应该使用equals还是==足够?

我知道使用字符串并不能保证每个唯一字符串只有一个实例,但我不确定其他盒装类型。

我的直觉是使用平等,但我想确保我不浪费表现。

编辑:该规范为拳击转换提供了一些保证。 从5.1.7节 :

如果被装箱的值p为true,false,一个字节,范围为\ u0000到\ u007f的字符,或者介于-128和127之间的int或短号,则让r1和r2为任意两次装箱转换的结果of p。 始终是r1 == r2的情况。

请注意,实施可以使用更大的池。

真的会避免编写依赖于它的代码。 不是因为它可能会失败,而是因为它并不明显 – 很少有人能够很好地了解规范。 (我以前认为它是依赖于实现的。)

您应该使用equals或比较基础值,即

 if (foo.equals(bar)) 

要么

 if (foo.intValue() == bar.intValue()) 

请注意,即使自动装箱保证使用固定值,其他呼叫者也总能创建单独的实例。

如果要比较任何对象的值,请使用.equals()

甚至(尤其是)如果那些对象是原始包装类型Byte,Character,Short,Integer,Long,Float,Double和Boolean。

== ”只是比较对象身份和你很少,你很想要的。 并且事实上并不是你想要的原始包装器。

仅在以下两种情况之一中使用==

  1. 比较中涉及的所有值都是原始类型(最好不是浮点数)
  2. 你真的想知道两个引用是否引用同一个对象(这包括enum的比较,因为值绑定到对象标识)
 //Quick test public class Test { public static void main(String[] args) { System.out.println("Are they equal? "+ (new Long(5) == new Long(5))); } } 

输出:

“他们是否相等?0”

回答:

不,他们不平等。 您必须使用.equals或比较它们的原始值。

Java语言规范5.1.7 :

如果被装箱的值p为true,false,一个字节,范围为\ u0000到\ u007f的字符,或者介于-128和127之间的int或短号,则让r1和r2为任意两次装箱转换的结果of p。 始终是r1 == r2的情况。

和:

讨论

理想情况下,装箱给定的原始值p将始终产生相同的参考。 实际上,使用现有的实现技术可能不可行。 上述规则是务实的妥协。 上面的最后一个条款要求将某些常见值装入无法区分的对象中。 实现可以懒惰或急切地缓存这些。

对于其他值,此公式不允许对程序员的盒装值的身份进行任何假设。 这将允许(但不要求)共享部分或全部这些引用。

这确保了在大多数常见情况下,行为将是期望的行为,而不会造成过度的性能损失,尤其是在小型设备上。 例如,较少内存限制的实现可以缓存所有字符和短路,以及-32K – + 32K范围内的整数和长整数。

所以,在某些情况下==会起作用,在许多其他情况下它不会起作用。 始终使用.equals是安全的,因为您不能(通常)获得实例的获取方式。

如果速度是一个因素(大多数.equals以==比较开始,或者至少它们应该)并且您可以保证它们的分配方式并且它们符合上述范围,那么==是安全的。

有些VM可能会增加这个大小,但是假设langauge规范指定的最小大小比依赖特定的VM行为更安全,除非你真的真的需要。

equals(Object o)方法的实现几乎总是以

 if(this == o) return true; 

所以即使==是真的,使用equals实际上并没有太大的性能影响。

我建议总是*在对象上使用equals方法。

*当然,有几次你不应该接受这个建议。

一般的答案是否定的 ,你不能保证对于相同的数值,你得到的Long对象是相同的(即使你限制自己使用Long.valueOf())。

但是,通过首先尝试测试引用的相等性(使用==)然后,如果失败,尝试equals(),可能会获得性能提升。 这一切都取决于额外的==测试和方法调用的比较成本…你的里程可能会有所不同,但值得尝试一个简单的循环测试,看看哪个更好。

值得注意的是,自动装箱值将使用合并对象(如果可用)。 这就是为什么(整数)0 ==(整数)0但是(整数)128!=(整数)128 for Java 6u13

我喜欢直观地看到结果:

  public static void main(String[] args) { Integer a = 126; //no boxed up conversion, new object ref Integer b = 126; //no boxed up conversion, re-use memory address System.out.println("Are they equal? " + (a == b)); // true Integer a1 = 140; //boxed up conversion, new object Integer b1 = 140; //boxed up conversion, new object System.out.println("Are they equal? " + (a1 == b1)); // false System.out.println("Are they equal? " + (new Long(5) == new Long(5))); // false } 

==比较对象引用,而equals(Object obj)比较对象相等性。 如果存在多个equals对象的实例,必须使用equals进行相等性比较。

例子:

 Integer i1 = new Integer(12345); Integer i2 = new Integer(12345); 

这些是不同的对象实例但是根据Integer的相等性是相等的,所以你必须使用equals(Object obj)

 public enum Gender { MALE, FEMALE; } 

在这种情况下,只有一个FEMALE实例存在,所以==是安全的。