toString(),==,equals()对象方法如何在引用和基元类型上以不同或相似的方式工作?

时间:2009-10-18 22:32:48

标签: java

toString()方法,==运算符和equals()方法在引用和基元类型上的工作方式有何不同或相似?

3 个答案:

答案 0 :(得分:7)

对于常规类型(包括String):

  • ==比较对象引用。它测试两个对象引用是否相等;即如果他们提到同一个物体。
  • equals(Object)测试此对象是否“等于”另一个对象。 “等于”意味着取决于对象的类如何定义相等性。 java.lang.Object类将equals(other)定义为this == other,但许多类都会覆盖此定义。
  • toString()提供了对象到String的简单转换。结果字符串的格式和内容是特定于类的,并且(从java.lang.Object合同的角度来看)不能保证它有意义。

对于(真)原始类型:

  • ==会比较类型的值和
  • equals()toString()未定义。 Java不允许您在原始值上调用方法。

然而,由于在某些上下文中 Java语言表明原始类型可以“自动装箱”以给出基本类型的相应包装类型的实例,因此这很复杂。例如int对应java.lang.Integer,依此类推。对于包装类:

  • ==的定义与任何其他参考类型相同,
  • equals()比较包装的值和
  • toString()格式化包装的值。

作品中的扳手如下所示:

int a = ...
int b = a;
Integer aa = a;        // autoboxing occurs
Integer bb = b;        // autoboxing occurs

assert a == b;         // always succeeds
assert aa.equals(bb);  // always succeeds
assert aa == bb;       // sometimes succeeds, sometimes fails.

最后一次失败的原因是JLS不保证给定原始值的自动装箱将始终给出相同的包装器对象。它在某些情况下(例如小整数),而不会用于其他情况(例如大整数)。

从上面的示例中学到的教训是,在引用类型上使用==时需要非常小心。只有在确实想要测试两个引用是否属于同一个对象时才使用它。如果您只想测试对象是否“相等”而没有调用equals()的开销,请不要使用它。

(另请注意,String是另一种类型,==在许多情况下会给您错误的答案;请参阅How do I compare strings in Java?。)

答案 1 :(得分:2)

对于引用类型,==将比较实际引用(对象所在的内存位置),其中equals方法执行数据比较。

出于性能原因,JVM有时会“字符串实例化”您的不可变字符串。导致这个:

String a = "abc";
String b = "abc";
if (a == b){ 
    //The if statement will evaluate to true, 
    //if your JVM string interns a and b, 
    //otherwise, it evaluates to false. 
}

http://en.wikipedia.org/wiki/String_interning

答案 2 :(得分:1)

'=='运算符适用于您具有的基本类型,在引用对象的情况下,它是引用本身。即a == b将原始类型的值作为int进行比较,但会比较引用类型的引用(而不是值)。调用true方法时,两个引用类型不同但具有相同值的对象将返回equals(),但a == b将为false。

对于基本类型,在调用方法时,类型先前已转换(装箱)为引用类型,然后调用该方法。这意味着对于基本类型a == b将产生与a.equals(b)相同的值,但在后一种情况下,在调用equals()方法之前会创建两个临时的盒装对象。这将使CPU操作中的操作更加昂贵,这可能是也可能不是问题,具体取决于它发生的位置。

也就是说,要比较基本类型值,您应该使用==,而要比较引用类型值,您应该使用.equals()方法。

toString()方法也是如此。在引用类型对象上调用时,它将调用适当的方法并生成一个String。当调用基本类型时,类型将被自动装箱,然后将在临时对象中调用该方法。在这种情况下,您可以调用相应的toString()静态方法(即对于int调用Integer.toString( myint )),这将避免创建临时对象。