Операции отношений == и != также работают с любыми объектами, но их смысл нередко сбивает с толку начинающих программистов на Java. Пример:
//: operators/Equivalence.java
public class Equivalence {
public static void main(String[] args) {
Integer n1 = new Integer(47);
Integer n2 = new Integer(47);
System.out.println(n1 == n2);
System.out.println(n1 != n2);
}
}
<spoiler text="Output:">
false
true
</spoiler> Выражение System.out.println(n1 == n2) выведет результат логического сравнения, содержащегося в скобках. Казалось бы, в первом случае результат должен быть истинным (true), а во втором — ложным (false), так как оба объекта типа Integer имеют одинаковые значения. Но в то время как содержимое объектов одинаково, ссылки на них разные, а операторы != и == сравнивают именно ссылки. Поэтому результатом первого выражения будет false, а второго — true. Естественно, такие результаты поначалу ошеломляют.
А если понадобится сравнить действительное содержимое объектов? Придется использовать специальный метод equals(), поддерживаемый всеми объектами (но не примитивами, для которых более чем достаточно операторов == и !=). Вот как это делается:
//: operators/EqualsMethod.java
public class EqualsMethod {
public static void main(String[] args) {
Integer n1 = new Integer(47);
Integer n2 = new Integer(47);
System.out.println(n1.equals(n2));
}
}
<spoiler text="Output:">
true
</spoiler> На этот раз результат окажется «истиной» (true), как и предполагалось. Но все не так просто, как кажется. Если вы создадите свой собственный класс вроде такого:
//: operators/EqualsMethod2.java
// Метод equals() по умолчанию не сравнивает содержимое.
class Value {
int i;
}
public class EqualsMethod2 {
public static void main(String[] args) {
Value v1 = new Value();
Value v2 = new Value();
v1.i = v2.i = 100;
System.out.println(v1.equals(v2));
}
}
<spoiler text="Output:">
false
</spoiler> мы вернемся к тому, с чего начали: результатом будет false. Дело в том, что метод equals() по умолчанию сравнивает ссылки. Следовательно, пока вы не переопределите этот метод в вашем новом классе, не получите желаемого результата. К сожалению, переопределение будет рассматриваться только в главе 8, а пока осторожность и общее понимание принципа работы equals() позволит избежать некоторых неприятностей.
Большинство классов библиотек Java реализуют метод equals() по-своему, сравнивая содержимое объектов, а не ссылки на них.