Java .equals между String и StringBuilder

class returntest
{



public static void main(String...args)
{

String name1 = "Test";
String s = new String("Test");
StringBuilder sb = new StringBuilder("Test");

System.out.println(name1.equals(sb)); //Line 1
System.out.println(name1.equals(s));  //Line 2
System.out.println(s.equals(sb));     // Line 3
System.out.println(s.equals(name1));  //Line 4
}

}

Ниже приведен вывод

false
true
false
true

Строка 1 возвращает, а строка 3 возвращает false.

Я не понимаю, почему компилятор не считает, что "name1" и "sb" содержат одно и то же значение.

Точно так же компилятор не считает, что «s» и «sb» содержат одну и ту же строку (оба не являются примитивами).

Может кто-нибудь объяснить вывод line1 и line3?


person UnderDog    schedule 31.08.2013    source источник


Ответы (12)


Потому что они оба разные objects.

String object!= StringBuilder object.

Но ваше сомнение

name1.equals(s)  returning true

Потому что в классе String метод equals переопределен таким образом.

И чтобы получить желаемый результат, преобразуйте StringBuilder в String.

System.out.println(s.equals(sb.toString())); //return true.

Если вы видите Исходный код String#equals()

1012    public boolean  equals(Object anObject) {
1013        if (this == anObject) {
1014            return true;
1015        }
1016        if (anObject instanceof String) {             //key line 
1017            String anotherString = (String)anObject;
1018            int n = count;
1019            if (n == anotherString.count) {
1020                char v1[] = value;
1021                char v2[] = anotherString.value;
1022                int i = offset;
1023                int j = anotherString.offset;
1024                while (n-- != 0) {
1025                    if (v1[i++] != v2[j++])
1026                        return false;
1027                }
1028                return true;
1029            }
1030        }
1031        return false;
1032    }

Строка if (anObject instanceof String) { всегда возвращает false, если вы передаете StringBuilder.

person Suresh Atta    schedule 31.08.2013

Причина двух случаев false заключается в том, что соответствующие equals(Object) методы указаны для работы именно так.

  • #P2# <блочная цитата> #P3#
  • #P4# <блочная цитата> #P5#

Таким образом, в строке № 1 и строке № 3 String.equals(Object) возвращает false, потому что sb не является String.

И если вы перевернете его и вызовете sb.equals(name1) или sb.equals(s), вы также получите false... потому что sb.equals(...) тестирует тот же объект.


Я не понимаю, почему компилятор не считает, что "name1" и "sb" содержат одно и то же значение.

Как видите, это не имеет никакого отношения к компилятору... и все, что связано с тем, как метод equals указан.

person Stephen C    schedule 31.08.2013

String.equals сравнивает не содержимое, а объекты

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        ...
    }
    return false;
}

StringBuilder вообще не переопределяет equals и наследует Object.equals

public boolean equals(Object obj) {
    return (this == obj);
}
person Evgeniy Dorofeev    schedule 31.08.2013

Используйте sb.toString() вместо прямого sb напрямую.

Это сравнивает эту строку с указанным объектом.

        System.out.println(name1.equals(sb.toString())); //Line 1
        System.out.println(name1.equals(s));  //Line 2
        System.out.println(s.equals(sb.toString()));     // Line 3
        System.out.println(s.equals(name1));  //Line 4

Это возвращает значение true для всей строки.

true
true
true
true
person bNd    schedule 31.08.2013

I dont understand why compiler does not think "name1" and "sb" as containing the same value

Поскольку equals() проверяет равенство ссылок на объекты, а не их содержимое, чтобы использовать его для сравнения того, что на самом деле содержат эти объекты, необходимо переопределить сам метод. Как вы знаете, класс string также переопределяет этот метод.

Здесь ,

String name1 = "Test";
StringBuilder sb = new StringBuilder("Test");

name1 является ссылкой на строку «Test», которая имеет тип String, а sb содержит ссылку на объект типа StringBuilder, поэтому они имеют совершенно разные ссылки. и, таким образом, equals возвращает false.

Теперь, почему System.out.println(name1.equals(s)); печатает true , потому что строковые литералы могут быть интернированы и когда вы делаете String s = new String("Test"); используется ссылка интернированного строкового объекта, поэтому они содержат одни и те же ссылки.

Поэтому, как предложили другие, вы должны использовать sb.toString() вместо sb

Ознакомьтесь с разделом Разница между типом объекта и типом ссылки, чтобы прояснить свои концепции. дальше.

person 0decimal0    schedule 31.08.2013

.equals() проверяет, равны ли два объекта. Обычно это включает проверку того, относятся ли оба объекта к одному и тому же типу.

Если вы хотите только проверить, равны ли значения, вы должны использовать sb.toString().

System.out.println(s.equals(sb.toString()));
person Moritz Petersen    schedule 31.08.2013

Вопрос Проблема при сравнении значения строки и объекта Java был продублирован на этот вопрос, поэтому разместите ответ здесь

Поскольку String , StringBuffer и StringBuilder реализуют CharSequence, вы можете проверить равенство содержимого, используя метод contentEquals в String

    "java".contentEquals(new StringBuffer("java")); // true
    "java".contentEquals(new StringBuilder("java")); // true
person Saravana    schedule 08.11.2016

String и StringBuilder - это два разных класса. equals() реализация проверяет равенство типов перед проверкой содержимого.

person S.D.    schedule 31.08.2013

System.out.println(s.equals(sb));
Вы получите false, так как метод equals() класса String реализован так, что передача null или объекта, отличного от String, дает false.

    public boolean equals(Object object){
          if(object instanceOf String){
             //do contnet comparison here
             //if both contents equal return true else fale
          }
          return false;
    }
person Prabhaker A    schedule 31.08.2013

«name1» и «s» являются объектами типа «String». Но "sb" имеет тип "StringBuilder".

Обычно метод equals() проверяет ссылку и тип. Таким образом, для приведенных выше утверждений 2 и 4 он возвращает true, поскольку они оба одинаковы.

Но объект StringBulider «sb» и s, name1 не являются одним и тем же типом w.r.t. Поэтому он возвращает ложь.

Если вы все еще хотите получить истинный результат сравнения, используйте sb.toString() и сравните с указанными выше значениями (s, name1).

person venky    schedule 31.08.2013

StringBuilder не переопределяет метод equals. Он наследует метод equals от класса Object. Если вы не сравниваете ссылки с одними и теми же объектами, он возвращает false.

Строка переопределяет метод equals, поэтому объекты возвращают true, если они эквивалентны по смыслу.

person Malwaregeek    schedule 31.08.2013

Простой ответ: вы не сравниваете яблоки и апельсины. Мы, люди, знаем, что это одно и то же, компилятор — это программа, которая не может действовать как человеческий интеллект.

По той же причине нельзя сказать, что есть два объекта, один из которых — автомобиль, а другой — разобранные части одного и того же автомобиля. Хотя оба имеют одинаковую конфигурацию :)

StringBuilder и String — совершенно разные объекты.

person dharam    schedule 31.08.2013