Предположим, у вас есть коллекция дружественных объектов, например,
class Friendly {
final int i;
Friendly( int i ) { this.i = i; }
public boolean equals( Object o ) {
return o != null && o instanceof Friendly && ((Friendly)o).i == this.i;
}
}
java.util.Collection c = new java.util.ArrayList();
for( int i = 0; i < 10; i++ )
c.add( new Friendly(i) );
и вы хотите вставить недружелюбный объект, который никогда не будет найден в коллекции contains
:
class Unfriendly extends Friendly {
Unfriendly( int i ) { super(i); }
public boolean equals( Object o ) { return false; }
}
Если contains
называется e.equals(o)
, тогда ваш зловещий план потерпит неудачу, поскольку дружественные элементы, уже находящиеся в коллекции, решат, равен ли объект недружественный им или нет ,
При вызове o.equals(e)
это недружелюбный объект, переданный contains
, который решает, чему он хочет быть равен, что позволяет вам использовать средство переопределения метода.
System.out.println("contains friendly? " + c.contains(new Friendly(1)));
#> contains friendly? true
System.out.println("contains unfriendly? " + c.contains(new Unfriendly(1)));
#> contains unfriendly? false
contains friendly?
- это true
, потому что мы используем ArrayList
; если бы мы использовали HashSet
или что-то еще хэшированное, становится необходимым также указать метод hashCode
.
Обратите внимание, что хотя контракт на contains
требует использования метода equals
, некоторые реализации могут не соответствовать этому, например, org.eclipse.emf.common.util.BasicEList
, тратя ваше время на то, чтобы вы это выяснили.
В этом случае вы должны сделать сравнение самостоятельно, например,
boolean contained = false;
for( Object e : c )
if( o.equals(e) ) { contained = true; break; }