How does the toString()
method, ==
operator, and equals()
method work differently or similarly开发者_如何学Go on reference and primitive types?
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. Thejava.lang.Object
class definesequals(other)
to bethis == 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 thejava.lang.Object
contract) there are no guarantees that it will be meaningful.
For (true) primitive types:
==
compares values of the type, andequals()
andtoString()
are not defined. Java does not allow you to call a method on a primitive value.
However this is complicated by the fact that in some contexts the Java language says that a primitive type can be "autoboxed" to give an instance of the primitive type's corresponding wrapper type; e.g. int
corresponds to java.lang.Integer
, and so on. For the wrapper classes:
==
is defined the same as for any other reference type,equals()
compares the wrapped values, andtoString()
formats the wrapped values.
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).
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 really want 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()
.
(Also note that String
is another type where ==
is going to give you the wrong answer in many situations; see How do I compare strings in Java?.)
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.
The JVM will sometimes "String intern" your immutable strings for performance reasons. Causing this:
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
The '==' operator works on the primitive type you have, that in the case of reference objects is the reference itself. That is a == b
will 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 true
when the equals()
method is called, but a == b
will be 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 == b
will 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.
That is, to compare primitive type values you should use ==
, while to compare reference type values you should use the .equals()
method.
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.
精彩评论