Как зайти в Даркнет?!
25th January, 01:11
4
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
892
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
912
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
905
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4380
0
Помогите пожалуйста решить задачи
24th November, 23:53
6084
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4350
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4395
0
Метода Крамера С++
23rd October, 11:55
4308
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2598
0
Теория (для языковых юристов и математически склонных):
equals() (javadoc) должен определить отношение эквивалентности (оно должно быть рефлексивным , симметричным и транзитивным). Кроме того, он должен быть согласованным (если объекты не изменяются, то он должен продолжать возвращать одно и то же значение). Кроме того, o.equals(null) всегда должен возвращать false.
hashCode() (javadoc) также должен быть согласованным (если объект не изменяется в терминах equals() , он должен продолжать возвращать то же самое значение).
Связь между этими двумя методами такова:
Если
a.equals(b), тоa.hashCode()должно быть таким же, какb.hashCode().
На практике:
Если вы переопределяете одно, то вы должны переопределить и другое.
Используйте тот же набор полей, который используется для вычисления equals() для вычисления hashCode() .
Используйте отличные вспомогательные классы EqualsBuilder и HashCodeBuilder из библиотеки Apache Commons Lang . Образец:
public class Person {
private String name;
private int age;
// ...
@Override
public int hashCode() {
return new HashCodeBuilder(17, 31). // two randomly chosen prime numbers
// if deriving: appendSuper(super.hashCode()).
append(name).
append(age).
toHashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Person))
return false;
if (obj == this)
return true;
Person rhs = (Person) obj;
return new EqualsBuilder().
// if deriving: appendSuper(super.equals(obj)).
append(name, rhs.name).
append(age, rhs.age).
isEquals();
}
}
Также помнить:
При использовании коллекции на основе hash или карты , например HashSet , LinkedHashSet , HashMap , Hashtable или WeakHashMap , убедитесь, что hashCode() ключевых объектов, помещенных в коллекцию, никогда не изменяются, пока объект находится в коллекции. Пуленепробиваемый способ обеспечить это - сделать ваши ключи неизменными, что имеет и другие преимущества .
Есть некоторые проблемы, которые стоит заметить, если вы имеете дело с классами, которые сохраняются с помощью объекта-отношения Mapper (ORM) как Hibernate, если вы не думали, что это уже было неоправданно сложно!
Лениво загруженные объекты являются подклассами
Если ваши объекты сохраняются с помощью ORM, во многих случаях вы будете иметь дело с динамическими прокси, чтобы избежать слишком ранней загрузки объекта из хранилища данных. Эти прокси реализованы как подклассы вашего собственного класса. Это означает, что this.getClass() == o.getClass() вернет false . Например:
Person saved = new Person("John Doe");
Long key = dao.save(saved);
dao.flush();
Person retrieved = dao.retrieve(key);
saved.getClass().equals(retrieved.getClass()); // Will return false if Person is loaded lazy
Если вы имеете дело с ORM, использование o instanceof Person -это единственное, что будет вести себя правильно.
Лениво загруженные объекты имеют null-поля
ORMs обычно используют геттеры для принудительной загрузки лениво загруженных объектов. Это означает, что person.name будет null , если person лениво загружается, даже если person.getName() принудительно загружает и возвращает "John Doe". По моему опыту, это происходит чаще всего в hashCode() и equals() годах .
Если вы имеете дело с ORM, убедитесь, что всегда используете геттеры, а не ссылки на поля в hashCode() и equals() .
Сохранение объекта приведет к изменению его состояния
Постоянные объекты часто используют поле id для хранения ключа объекта. Это поле будет автоматически обновляться при первом сохранении объекта. Не используйте поле id в hashCode() . Но вы можете использовать его в equals() .
Шаблон, который я часто использую, это
if (this.getId() == null) {
return this == other;
}
else {
return this.getId().equals(other.getId());
}
Но: вы не можете включить getId() в hashCode() . Если вы это сделаете, то при сохранении объекта его hashCode изменится. Если объект находится в HashSet, вы "never" найдете его снова.
В моем примере Person я, вероятно, использовал бы getName() для hashCode и getId() плюс getName() (только для паранойи) для equals() . Это нормально, если есть некоторый риск "collisions" для hashCode(), но никогда не хорошо для equals() .
hashCode() должен использовать неизменяемое подмножество свойств из equals()
Уточнение по поводу obj.getClass() != getClass() .
Это утверждение является результатом того, что equals() является наследованием недружественным. JLS (спецификация языка Java) указывает, что если A.equals(B) == true , то B.equals(A) также должно возвращать true . Если вы опустите эту инструкцию, то наследование классов, которые переопределяют equals() (и изменяют его поведение), нарушит эту спецификацию.
Рассмотрим следующий пример того, что происходит, когда оператор опущен:
class A {
int field1;
A(int field1) {
this.field1 = field1;
}
public boolean equals(Object other) {
return (other != null && other instanceof A && ((A) other).field1 == field1);
}
}
class B extends A {
int field2;
B(int field1, int field2) {
super(field1);
this.field2 = field2;
}
public boolean equals(Object other) {
return (other != null && other instanceof B && ((B)other).field2 == field2 && super.equals(other));
}
}
Делая new A(1).equals(new A(1)) также, new B(1,1).equals(new B(1,1)) результат выдают истинным, как и положено.
Все это выглядит очень хорошо, но посмотрите, что произойдет, если мы попытаемся использовать оба класса:
A a = new A(1);
B b = new B(1,1);
a.equals(b) == true;
b.equals(a) == false;
Очевидно, что это неправильно.
Если вы хотите обеспечить симметричное условие. a=b, если b=a и принцип подстановки Лискова вызывают super.equals(other) не только в случае экземпляра B , но и проверяют после для экземпляра A :
if (other instanceof B )
return (other != null && ((B)other).field2 == field2 && super.equals(other));
if (other instanceof A) return super.equals(other);
else return false;
Который будет выводить:
a.equals(b) == true;
b.equals(a) == true;
Где, если a не является ссылкой на B, то это может быть ссылка на класс A (потому что вы расширяете его), в этом случае вы также вызываете super.equals() .
Для реализации, удобной для наследования, ознакомьтесь с решением Тала Коэна, как правильно реализовать метод equals()?
Резюме:
В своей книге Effective Java Programming Language Guide (Addison-Wesley, 2001) Джошуа блох утверждает, что "просто нет способа расширить экземпляр класса и добавить аспект, сохраняя при этом контракт equals.- Тал не согласен.
Его решение состоит в том, чтобы реализовать equals(), вызвав другой несимметричный blindlyEquals() в обоих направлениях. blindlyEquals() переопределяется подклассами, equals() наследуется и никогда не переопределяется.
Пример:
class Point {
private int x;
private int y;
protected boolean blindlyEquals(Object o) {
if (!(o instanceof Point))
return false;
Point p = (Point)o;
return (p.x == this.x && p.y == this.y);
}
public boolean equals(Object o) {
return (this.blindlyEquals(o) && o.blindlyEquals(this));
}
}
class ColorPoint extends Point {
private Color c;
protected boolean blindlyEquals(Object o) {
if (!(o instanceof ColorPoint))
return false;
ColorPoint cp = (ColorPoint)o;
return (super.blindlyEquals(cp) &&
cp.color == this.color);
}
}
Обратите внимание, что equals() должен работать через иерархии наследования, если должен быть удовлетворен Принцип подстановки Лискова .
До сих пор удивляюсь, что никто не рекомендовал библиотеку гуавы для этого.
//Sample taken from a current working project of mine just to illustrate the idea
@Override
public int hashCode(){
return Objects.hashCode(this.getDate(), this.datePattern);
}
@Override
public boolean equals(Object obj){
if ( ! obj instanceof DateAndPattern ) {
return false;
}
return Objects.equal(((DateAndPattern)obj).getDate(), this.getDate())
&& Objects.equal(((DateAndPattern)obj).getDate(), this.getDatePattern());
}
Есть два метода в супер классе как java.lang.Object. Нам нужно переопределить их на пользовательский объект.
public boolean equals(Object obj)
public int hashCode()
Равные объекты должны производить один и тот же код hash до тех пор, пока они равны, однако неравные объекты не должны производить различные коды hash.
public class Test
{
private int num;
private String data;
public boolean equals(Object obj)
{
if(this == obj)
return true;
if((obj == null) || (obj.getClass() != this.getClass()))
return false;
// object must be Test at this point
Test test = (Test)obj;
return num == test.num &&
(data == test.data || (data != null && data.equals(test.data)));
}
public int hashCode()
{
int hash = 7;
hash = 31 * hash + num;
hash = 31 * hash + (null == data ? 0 : data.hashCode());
return hash;
}
// other methods
}
Если вы хотите получить больше, пожалуйста, проверьте эту ссылку как http://www.javaranch.com/journal/2002/10/equalhash.html
Это еще один пример, http://java67.blogspot.com/2013/04/example-of-overriding-equals-hashcode-compareTo-java-method.html
Веселитесь! @.@
Есть несколько способов проверить равенство классов перед проверкой равенства членов, и я думаю, что оба они полезны в правильных обстоятельствах.
- Используйте оператор
instanceof. - Используйте
this.getClass().equals(that.getClass()).
Я использую #1 в реализации final equals или при реализации интерфейса, который предписывает алгоритм для equals (например, java.util collection interfaces—the right way для проверки с помощью (obj instanceof Set) или любого другого интерфейса, который вы реализуете). Обычно это плохой выбор, когда равные могут быть переопределены, потому что это нарушает свойство симметрии.
Опция #2 позволяет безопасно расширить класс без переопределения равенства или нарушения симметрии.
Если ваш класс также Comparable, то методы equals и compareTo также должны быть согласованными. Вот шаблон для метода equals в классе Comparable :
final class MyClass implements Comparable<MyClass>
{
…
@Override
public boolean equals(Object obj)
{
/* If compareTo and equals aren't final, we should check with getClass instead. */
if (!(obj instanceof MyClass))
return false;
return compareTo((MyClass) obj) == 0;
}
}
Для равных, посмотрите на Секреты равных Анжелики Лангер . Мне это очень нравится. Она также отлично разбирается в дженериках в 29-м году . Просмотрите ее другие статьи здесь (прокрутите вниз до "Core Java"), где она также переходит к части 2 и "mixed type comparison". Получайте удовольствие, читая их!
equals() метод используется для определения равенства двух объектов.
поскольку int значение 10 всегда равно 10. Но этот метод equals() - о равенстве двух объектов. Когда мы говорим объект, он будет иметь свойства. Для принятия решения о равенстве рассматриваются эти свойства. Нет необходимости, чтобы все свойства были приняты во внимание для определения равенства, и в отношении определения класса и контекста это может быть решено. Тогда метод equals() может быть переопределен.
мы всегда должны переопределять метод hashCode() всякий раз, когда мы переопределяем метод equals(). А если нет, то что тогда произойдет? Если мы используем хэш-таблицы в нашем приложении, оно не будет вести себя так, как ожидалось. Поскольку параметр hashCode используется для определения равенства сохраненных значений, он не возвращает правильное соответствующее значение для ключа.
Данная реализация по умолчанию является hashCode() метод в классе объектов использует внутренний адрес объекта и преобразует его в целое число и возвращает его.
public class Tiger {
private String color;
private String stripePattern;
private int height;
@Override
public boolean equals(Object object) {
boolean result = false;
if (object == null || object.getClass() != getClass()) {
result = false;
} else {
Tiger tiger = (Tiger) object;
if (this.color == tiger.getColor()
&& this.stripePattern == tiger.getStripePattern()) {
result = true;
}
}
return result;
}
// just omitted null checks
@Override
public int hashCode() {
int hash = 3;
hash = 7 * hash + this.color.hashCode();
hash = 7 * hash + this.stripePattern.hashCode();
return hash;
}
public static void main(String args[]) {
Tiger bengalTiger1 = new Tiger("Yellow", "Dense", 3);
Tiger bengalTiger2 = new Tiger("Yellow", "Dense", 2);
Tiger siberianTiger = new Tiger("White", "Sparse", 4);
System.out.println("bengalTiger1 and bengalTiger2: "
+ bengalTiger1.equals(bengalTiger2));
System.out.println("bengalTiger1 and siberianTiger: "
+ bengalTiger1.equals(siberianTiger));
System.out.println("bengalTiger1 hashCode: " + bengalTiger1.hashCode());
System.out.println("bengalTiger2 hashCode: " + bengalTiger2.hashCode());
System.out.println("siberianTiger hashCode: "
+ siberianTiger.hashCode());
}
public String getColor() {
return color;
}
public String getStripePattern() {
return stripePattern;
}
public Tiger(String color, String stripePattern, int height) {
this.color = color;
this.stripePattern = stripePattern;
this.height = height;
}
}
Пример Вывода Кода:
bengalTiger1 and bengalTiger2: true
bengalTiger1 and siberianTiger: false
bengalTiger1 hashCode: 1398212510
bengalTiger2 hashCode: 1398212510
siberianTiger hashCode: –1227465966