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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1586223/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 17:10:52  来源:igfitidea点击:

How does the toString(), ==, equals() object methods work differently or similarly on reference and primitive types?

java

提问by JAVANEWBIE

How does the toString()method, ==operator, and equals()method work differently or similarly on reference and primitive types?

toString()方法、==运算符和equals()方法在引用和原始类型上如何以不同或相似的方式工作?

回答by Stephen C

For regular types (including String):

对于常规类型(包括字符串):

  • ==compares object references. It tests if two object references are equal; i.e. if they refer to the same object.
  • equals(Object)tests if this object is "equal to" another one. What "equal to" means depends on how the object's class defines equality. The java.lang.Objectclass defines equals(other)to be this == other, but many classes override this definition.
  • toString()provides a simple conversion of the object to a String. The format and content of the resulting String is class specific, and (from the perspective of the java.lang.Objectcontract) there are no guarantees that it will be meaningful.
  • ==比较对象引用。它测试两个对象引用是否相等;即如果它们指的是同一个对象。
  • equals(Object)测试此对象是否“等于”另一个对象。“等于”的含义取决于对象的类如何定义相等。的java.lang.Object类定义equals(other)this == other,但很多类重写这个定义。
  • toString()提供对象到字符串的简单转换。结果字符串的格式和内容是特定于类的,并且(从java.lang.Object合同的角度来看)不能保证它是有意义的。

For (true) primitive types:

对于(真)原始类型:

  • ==compares values of the type, and
  • equals()and toString()are not defined. Java does not allow you to call a method on a primitive value.
  • ==比较类型的值,和
  • equals()并且toString()没有定义。Java 不允许您对原始值调用方法。

However this is complicated by the fact that in some contextsthe Java language says that a primitive type can be "autoboxed" to give an instance of the primitive type's corresponding wrapper type; e.g. intcorresponds to java.lang.Integer, and so on. For the wrapper classes:

然而,这很复杂,因为在某些上下文中,Java 语言说原始类型可以“自动装箱”以给出原始类型相应包装器类型的实例;例如int对应于java.lang.Integer,等等。对于包装类:

  • ==is defined the same as for any other reference type,
  • equals()compares the wrapped values, and
  • toString()formats the wrapped values.
  • ==定义与任何其他引用类型相同,
  • equals()比较包装的值,和
  • toString()格式化包装的值。

The spanner in the works is illustrated by the following:

作品中的扳手如下图所示:

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.

The reason that the last sometimes fails is that the JLS does NOT guarantee that autoboxing a given primitive value will always give the same wrapper object. It will in some cases (e.g. for small integers), and won't for others (e.g. large integers).

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

The lesson to be learned from the example above is that you need to be very careful about using ==on a reference type. Only use it when you reallywant to test if two references are to the same object. Don't use it if you just want to test if the objects are "equal" without the overhead of calling equals().

从上面的例子中学到的教训是,==在引用类型上使用时需要非常小心。仅当您真的想测试两个引用是否指向同一个对象时才使用它。如果您只想测试对象是否“相等”而没有调用equals().

(Also note that Stringis another type where ==is going to give you the wrong answer in many situations; see How do I compare strings in Java?.)

(另请注意,这String==在许多情况下会给您错误答案的另一种类型;请参阅如何比较 Java 中的字符串?。)

回答by Babak Naffas

For reference types, == will compare the actual reference (where in memory the object resides) where as the equals method performs a comparison of the data.

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

The JVM will sometimes "String intern" your immutable strings for performance reasons. Causing this:

出于性能原因,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

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

回答by David Rodríguez - dribeas

The '==' operator works on the primitive type you have, that in the case of reference objects is the reference itself. That is a == bwill compare the values for primitive types as int, but will compare the reference (not the value) for reference types. Two objects of reference type that are not the same but have the same value will return truewhen the equals()method is called, but a == bwill be false.

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

For primitive types, when calling a method, the type is previously converted (boxed) to a reference type and then the method is called. This means that for primitive types a == bwill yield the same value as a.equals(b), but in the latter case two temporary boxed objects are created prior to calling the equals()method. This will make the operation more expensive in CPU time which may or may not be a problem depending on where it happens.

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

That is, to compare primitive type values you should use ==, while to compare reference type values you should use the .equals()method.

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

The same happens with the toString()method. When called on a reference type object, it will call the appropriate method and produce a String. When called on a primitive type, the type will be autoboxed and then the method will be called in the temporary object. In this case, you can call the appropriate toString()static method (i.e. for int call Integer.toString( myint )) this will avoid creating the temporary object.

情况与此相同的toString()方法。当在引用类型对象上调用时,它将调用适当的方法并生成一个字符串。当在原始类型上调用时,该类型将被自动装箱,然后将在临时对象中调用该方法。在这种情况下,您可以调用适当的toString()静态方法(即对于 int call Integer.toString( myint )),这将避免创建临时对象。