.equals() для пользовательского класса в Java
Пожалуйста, смотрите код ниже
class TestToString
{
public static void main(String args[])
{
CheckToString cs = new CheckToString (2);
CheckToString c = new CheckToString (2);
if( cs.equals(c))
System.out.println(" Both objects are equal");
else
System.out.println(" Unequal objects ");
}
}
class CheckToString
{
int i;
CheckToString ()
{
i=10;
}
CheckToString (int a)
{
this.i=a;
}
}
Вывод: неравные объекты
Но я ожидал, что результат будет
Оба объекта равны
Я понял, что оба объекта имеют разные ссылки,
System.out.println(cs); //com.sample.personal.checkToString@19821f
System.out.println(c); //com.sample.personal.checkToString@addbf1
но я спрашивал, почему у них разные ссылки? тогда как в приведенном ниже случае объекты имеют одинаковые области памяти.
Integer a = new Integer(2);
Integer b = new Integer(2);
System.out.println(a); //2
System.out.println(b); //2
Я сравниваю объект пользовательского класса с объектом предварительно определенного класса. Кажется, что объект пользовательского класса ведет себя так же, как и объект целочисленного класса, значение которого превышает от -128 до 127. Почему ссылки различны в обоих случаях? (то же самое для класса Integer, имеющего значение в диапазоне от -128 до 127 и различного для пользовательского класса)
6 ответов
Реализация по умолчанию equals
проверяет ссылки. Вы создаете 2 разных объекта, которые не ссылаются на одну и ту же вещь в памяти.
Достойная реализация equals будет что-то вроде:
public boolean equals(Object o) {
if (!(o instanceof CheckToString)) {
return false;
}
CheckToString other = (CheckToString) o;
return i == other.i;
}
При переопределении equals
нужно переопределить hashCode
, тоже.
Всякий раз, когда вы говорите new CheckToString()
, вы создаете новый объект в памяти, так что совершенно другая ссылка, чем другой new CheckToString()
, Неважно, что находится внутри определения объекта.
То, что вы упоминаете о Integer, верно, но относится к Integer
, а не к пользовательскому объекту, который вы создали.
Вы должны переопределить equals
метод в вашем CheckToString
учебный класс:
@Override
public boolean equals(Object o){
if(this==o){
return true;
}
if(o instanceof CheckString){
CheckString other = (CheckString) o;
return this.i == other.i;
}
return false;
}
Рекомендуется при переопределении equals
Вы также переопределите hashCode
, так что вы можете использовать свой объект в хешированных коллекциях (например, HasSet, LinkedHasSet, HashMap). В таком случае, поскольку ваш класс выглядит как обертка над примитивным целым числом, я думаю, вы могли бы вернуть само целое число.
@Override
public int hashCode(){
return i;
}
И, наконец, всегда рекомендуется переопределить toString
, так что каждый раз, когда вы смотрите на экземпляры вашего класса, вы видите дружественное, удобочитаемое представление вашего объекта.
@Override
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append(this.getClass().getSimpleName()).append("[");
sb.append("i: ").append(i).append("]");
return sb.toString();
}
Вы должны определить свой собственный метод toString для возврата значения i
И ваш собственный метод равных.
class checkToString
{
int i;
public checkToString()
{
i=10;
}
public checkToString(int a)
{
this.i=a;
}
public String toString(){ return "" + i;}
public boolean equals(checkToString a){ return a.toString().equals(this.toString());}
}
Попробуйте сейчас. Это также может быть сделано без toString().
как это:
public boolean equals(checkToString a){ return (this.i == a.i); }
2 объекта явно не указывают в одну и ту же область памяти (обратите внимание, что вы сравниваете ссылки на объекты). Для получения дополнительной информации см. JavaDoc объекта класса и соответствующие equals()
Митос
Чтобы сравнить их строковое представление, вы можете сделать эту модификацию:
class TestToString
{
public static void main(String args[])
{
CheckToString cs = new CheckToString(2);
CheckToString c = new CheckToString(2);
if( cs.toString().equalsIgnoreCase(c.toString()))
System.out.println(" Both objects are equal");
else
System.out.println(" Unequal objects ");
}
}
class CheckToString
{
int i;
CheckToString()
{
i=10;
}
CheckToString(int a)
{
this.i=a;
}
public String toString(){
return String.valueOf(i);
}
}
PS: Обратите внимание также на изменение в случае объекта ( Java Conventions)
По умолчанию метод equals проверяет только хэш-коды любых двух объектов. Итак, если вам нужно, чтобы метод equals возвращал результат в зависимости от любого базового свойства в вашем объекте, вам придется соответствующим образом переопределить метод equals.
Метод equals сравнивается на основе ссылки по умолчанию в любом определяемом пользователем классе, но если вы переопределяете метод equals в текущем классе, то он сравнивается на основе содержимого... но в java.lang.StringClass он сравнивается по основа содержания всегда