String.equals против ==

Этот код разделяет строку на токены и сохраняет их в массиве строк, а затем сравнивает переменную с первым домом... почему он не работает?

public static void main(String...aArguments) throws IOException {

    String usuario = "Jorman";
    String password = "14988611";

    String strDatos = "Jorman 14988611";
    StringTokenizer tokens = new StringTokenizer(strDatos, " ");
    int nDatos = tokens.countTokens();
    String[] datos = new String[nDatos];
    int i = 0;

    while (tokens.hasMoreTokens()) {
        String str = tokens.nextToken();
        datos[i] = str;
        i++;
    }

    //System.out.println (usuario);

    if ((datos[0] == usuario)) {
        System.out.println("WORKING");
    }
}

20 ответов

Решение

Использовать string.equals(Object other) функция для сравнения строк, а не == оператор.

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

if (usuario.equals(datos[0])) {
    ...
}

NB: сравнение выполняется на "usuario", потому что это гарантированно ненулевое значение в вашем коде, хотя вы все равно должны убедиться, что у вас есть некоторые токены в datos массив, в противном случае вы получите исключение массива за пределами границ.

Знакомьтесь, Джорман

Джорман успешный бизнесмен и имеет 2 дома.

Но другие этого не знают.

Это тот же Джорман?

Когда вы спрашиваете соседей с улиц Мэдисон или Берк, это единственное, что они могут сказать:

Используя одну только резиденцию, сложно подтвердить, что это тот же Джорман. Поскольку это 2 разных адреса, естественно предположить, что это 2 разных человека.

Вот так оператор == ведет себя. Так будет сказано, что datos[0]==usuario ложно, потому что он сравнивает только адреса.

Следователь на помощь

Что если мы отправим следователя? Мы знаем, что это тот же Джорман, но нам нужно это доказать. Наш детектив внимательно рассмотрит все физические аспекты. При тщательном расследовании агент сможет сделать вывод, является ли это тот же человек или нет. Давайте посмотрим, как это происходит в терминах Java.

Вот исходный код String equals() метод:

Он сравнивает строки по символам, чтобы прийти к выводу, что они действительно равны.

Вот как струна equals метод ведет себя. Так datos[0].equals(usuario) вернет true, потому что он выполняет логическое сравнение.

Хорошо отметить, что в некоторых случаях использование оператора "==" может привести к ожидаемому результату, потому что способ, которым java обрабатывает строки - строковые литералы интернированы (см. String.intern()) во время компиляции - так что когда пишешь например "hello world" в двух классах и сравнив эти строки с "==" вы можете получить результат: true, что ожидается в соответствии со спецификацией; когда вы сравниваете одни и те же строки (если они имеют одинаковое значение), когда первая строка является строковым литералом (т.е. определяется через "i am string literal") и второе строится во время выполнения т.е. с "новым" ключевым словом, как new String("i am string literal"), == (равенство) оператор возвращает ложь, потому что оба они являются различными экземплярами String учебный класс.

Единственно правильный путь - использование .equals() -> datos[0].equals(usuario) , == говорит только, если два объекта являются одним и тем же экземпляром объекта (т.е. имеют один и тот же адрес памяти)

Обновление: 01.04.2013 Я обновил этот пост из-за комментариев ниже, которые как-то правы. Первоначально я объявил, что интернирование (String.intern) является побочным эффектом оптимизации JVM. Хотя это, безусловно, экономит ресурсы памяти (что я имел в виду под "оптимизацией"), в основном это особенность языка

equals() функция является методом Object класс, который должен быть переопределен программистом. String Класс переопределяет его, чтобы проверить, равны ли две строки, т.е. по содержанию, а не по ссылке.

== Оператор проверяет, совпадают ли ссылки на оба объекта.

Рассмотрим программы

String abc = "Awesome" ;
String xyz =  abc;

if(abc == xyz)
     System.out.println("Refers to same string");

Здесь abc а также xyzоба относятся к одному и тому же String"Awesome", Отсюда и выражение (abc == xyz) является true,

String abc = "Hello World";
String xyz = "Hello World";

if(abc == xyz)
    System.out.println("Refers to same string");
else
    System.out.println("Refers to different strings");

if(abc.equals(xyz))
     System.out.prinln("Contents of both strings are same");
else
     System.out.prinln("Contents of strings are different");

Вот abc а также xyz две разные строки с одинаковым содержанием "Hello World", Отсюда и выражение (abc == xyz) является false в то время как (abc.equals(xyz)) является true,

Надеюсь, вы поняли разницу между == а также <Object>.equals()

Благодарю.

The == operator checks if the two references point to the same object or not.
.equals() checks for the actual string content (value).

Обратите внимание, что метод.equals() принадлежит классу Object (суперкласс всех классов). Вам необходимо переопределить его в соответствии с требованиями вашего класса, но для String он уже реализован и проверяет, имеют ли две строки одинаковое значение или нет.

Case1)
String s1 = "Stack Overflow";
String s2 = "Stack Overflow";
s1 == s1;      // true
s1.equals(s2); // true
Reason: String literals created without null are stored in the string pool in the permgen area of the heap. So both s1 and s2 point to the same object in the pool.
Case2)
String s1 = new String("Stack Overflow");
String s2 = new String("Stack Overflow");
s1 == s2;      // false
s1.equals(s2); // true
Reason: If you create a String object using the `new` keyword a separate space is allocated to it on the heap.

== тесты на референтное равенство.

.equals() тесты на равенство значений.

Следовательно, если вы действительно хотите проверить, имеют ли две строки одинаковое значение, вы должны использовать .equals() (за исключением нескольких ситуаций, когда вы можете гарантировать, что две строки с одинаковым значением будут представлены одним и тем же объектом, например: String интернирование).

== для проверки, являются ли две строки одинаковыми Object,

// These two have the same value
new String("test").equals("test") ==> true 

// ... but they are not the same object
new String("test") == "test" ==> false 

// ... neither are these
new String("test") == new String("test") ==> false 

// ... but these are because literals are interned by 
// the compiler and thus refer to the same object
"test" == "test" ==> true 

// concatenation of string literals happens at compile time resulting in same objects
"test" == "te" + "st"  ==> true

// but .substring() is invoked at runtime, generating distinct objects
"test" == "!test".substring(1) ==> false

Важно отметить, что == намного дешевле чем equals() (сравнение с одним указателем вместо цикла), таким образом, в ситуациях, когда это применимо (то есть вы можете гарантировать, что имеете дело только с интернированными строками), это может привести к значительному повышению производительности. Однако такие ситуации редки.

Вместо

datos[0] == usuario

использование

datos[0].equals(usuario)

== сравнивает ссылку на переменную где .equals() сравнивает значения, которые вы хотите.

Давайте проанализируем следующую Java, чтобы понять идентичность и равенство строк:

public static void testEquality(){
    String str1 = "Hello world.";
    String str2 = "Hello world.";

    if (str1 == str2)
        System.out.print("str1 == str2\n");
    else
        System.out.print("str1 != str2\n");

    if(str1.equals(str2))
        System.out.print("str1 equals to str2\n");
    else
        System.out.print("str1 doesn't equal to str2\n");

    String str3 = new String("Hello world.");
    String str4 = new String("Hello world.");

    if (str3 == str4)
        System.out.print("str3 == str4\n");
    else
        System.out.print("str3 != str4\n");

    if(str3.equals(str4))
        System.out.print("str3 equals to str4\n");
    else
        System.out.print("str3 doesn't equal to str4\n");
}

Когда первая строка кода String str1 = "Hello world." выполняет, строка \Hello world."создан, и переменная str1 относится к этому. Другая строка "Hello world." больше не будет создаваться при выполнении следующей строки кода из-за оптимизации. Переменная str2 также относится к существующим ""Hello world.",

Оператор == проверяет идентичность двух объектов (ссылаются ли две переменные на один и тот же объект). поскольку str1 а также str2 ссылаются на одну и ту же строку в памяти, они идентичны друг другу. Метод equals проверяет равенство двух объектов (имеют ли два объекта одинаковое содержимое). Конечно, содержание str1 а также str2 такие же.

Когда код String str3 = new String("Hello world.") выполняет новый экземпляр строки с содержимым "Hello world." создан, и на него ссылается переменная str3, А потом еще один экземпляр строки с содержанием "Hello world." создается снова и упоминаетсяstr4, поскольку str3 а также str4 ссылаются на два разных экземпляра, они не идентичны, но их содержание одинаково.

Поэтому вывод содержит четыре строки:

Str1 == str2

Str1 equals str2

Str3! = str4

Str3 equals str4

Это также будет работать, если вы позвоните intern() на строку перед вставкой в ​​массив. Стажированные строки равны ссылкам (==) тогда и только тогда, когда они равны по стоимости (equals().)

public static void main (String... aArguments) throws IOException {

String usuario = "Jorman";
String password = "14988611";

String strDatos="Jorman 14988611";
StringTokenizer tokens=new StringTokenizer(strDatos, " ");
int nDatos=tokens.countTokens();
String[] datos=new String[nDatos];
int i=0;

while(tokens.hasMoreTokens()) {
    String str=tokens.nextToken();
    datos[i]= str.intern();            
    i++;
}

//System.out.println (usuario);

if(datos[0]==usuario) {  
     System.out.println ("WORKING");    
}

Вы должны использовать строку equals для сравнения двух строк на равенство, а не operator ==, который просто сравнивает ссылки.

Если вы собираетесь сравнивать любое присвоенное значение строки, т.е. примитивную строку, то будут работать и "==", и.equals, но для нового строкового объекта вы должны использовать только.equals, а здесь "==" не будет работать.

Пример:

String a = "name";

String b = "name";

if(a == b) а также (a.equals(b)) вернет истину.

Но

String a = new String("a");

В этом случае if(a == b) вернусь false

Так что лучше использовать .equals оператор...

В общем-то .equals используется для Object сравнение, где вы хотите проверить, если два Objects имеют одинаковое значение.

== для сравнения (это два Objects тот же самый Object в кучу) и проверить, если Object нулевой. Он также используется для сравнения значений примитивных типов.

== Оператор сравнивает ссылку на объект в Java. Вы можете использовать строки equals метод.

String s = "Test";
if(s.equals("Test"))
{
    System.out.println("Equal");
}

@Melkhiah66 Вы можете использовать метод equals вместо метода '==', чтобы проверить равенство. Если вы используете intern(), то он проверяет, находится ли объект в пуле, если присутствует, и возвращает равный, иначе неравный. Метод equals внутренне использует хэш-код и получает требуемый результат.

public class Demo
{
  public static void main(String[] args)
  {
              String str1 = "Jorman 14988611";
    String str2 = new StringBuffer("Jorman").append(" 14988611").toString();
    String str3 = str2.intern();
    System.out.println("str1 == str2 " + (str1 == str2));           //gives false
    System.out.println("str1 == str3 " + (str1 == str3));           //gives true
    System.out.println("str1 equals str2 " + (str1.equals(str2)));  //gives true
    System.out.println("str1 equals str3 " + (str1.equals(str3)));  //gives true
  }
}

Я знаю, что это старый вопрос, но вот как я на него смотрю (я считаю очень полезным):


Технические объяснения

В Java все переменные являются либо примитивными типами, либо ссылками.

(Если вам нужно знать, что такое ссылка: "переменные объекта" - это просто указатели на объекты. Object something = ...что-то действительно адрес в памяти (число).)

== сравнивает точные значения. Таким образом, он сравнивает, совпадают ли значения примитивов или ссылки (адреса) одинаковы. Вот почему == часто не работает со строками; Строки являются объектами, и делать == с двумя строковыми переменными просто сравнивает, если адрес в памяти такой же, как указали другие. .equals() вызывает метод сравнения объектов, который сравнивает фактические объекты, указанные в ссылках. В случае строк, он сравнивает каждый символ, чтобы увидеть, равны ли они.


Интересная часть:

Так почему же == иногда возвращать true для строк? Обратите внимание, что строки являются неизменяемыми. В вашем коде, если вы делаете

String foo = "hi";
String bar = "hi";

Так как строки неизменны (когда вы звоните .trim() или что-то, он создает новую строку, не изменяя исходный объект, указанный в памяти), вам не нужно два разных String("hi") объекты. Если компилятор умный, байт-код будет читать только один String("hi") объект. Так что если вы делаете

if (foo == bar) ...

сразу после этого они указывают на один и тот же объект и вернут true. Но вы редко намерены это. Вместо этого вы запрашиваете ввод данных пользователем, который создает новые строки в разных частях памяти и т. Д. И т. Д.

Примечание: если вы делаете что-то вроде baz = new String(bar) компилятор все еще может понять, что это одно и то же. Но главное - когда компилятор видит буквенные строки, он может легко оптимизировать те же строки.

Я не знаю, как это работает во время выполнения, но я предполагаю, что JVM не хранит список "живых строк" ​​и проверяет, существует ли такая же строка. (например, если вы дважды прочитаете строку ввода, и пользователь введет один и тот же ввод дважды, он не будет проверять, совпадает ли вторая строка ввода с первой, и укажет их на одну и ту же память). Это сэкономит немного кучи памяти, но настолько незначительно, что накладные расходы не стоят того. Опять же, дело в том, что компилятору легко оптимизировать буквенные строки.

Там у вас есть это... песчаное объяснение == против .equals() и почему это кажется случайным.

Оператор == - это простое сравнение значений.
Для ссылок на объекты (значения) являются (ссылки). Таким образом, x == y возвращает true, если x и y ссылаются на один и тот же объект.

a==b

Сравнивает ссылки, а не значения. Использование == с объектными ссылками, как правило, ограничивается следующим:

  1. Сравнивая, чтобы увидеть, если ссылка null,

  2. Сравнение двух значений enum. Это работает, потому что есть только один объект для каждого enum постоянная.

  3. Вы хотите знать, если две ссылки на один и тот же объект

"a".equals("b")

Сравнивает значения на равенство. Поскольку этот метод определен в Object класс, из которого происходят все остальные классы, он автоматически определяется для каждого класса. Тем не менее, он не выполняет интеллектуальное сравнение для большинства классов, если класс не переопределяет его. Он был определен значимым образом для большинства основных классов Java. Если он не определен для (пользовательского) класса, он ведет себя так же, как ==,

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

Кто-то сказал в посте выше, что == используется для int и для проверки нулей. Он также может использоваться для проверки логических операций и типов символов.

Будьте очень осторожны и дважды проверьте, что вы используете символ, а не String. например

    String strType = "a";
    char charType = 'a';

для строк вы бы тогда проверили это было бы правильно

    if(strType.equals("a")
        do something

но

    if(charType.equals('a')
        do something else

было бы неправильно, вам нужно сделать следующее

    if(charType == 'a')
         do something else

Используйте Split, а не tokenizer, он наверняка предоставит вам точный вывод, например:

string name="Harry";
string salary="25000";
string namsal="Harry 25000";
string[] s=namsal.split(" ");
for(int i=0;i<s.length;i++)
{
System.out.println(s[i]);
}
if(s[0].equals("Harry"))
{
System.out.println("Task Complete");
}

После этого я уверен, что вы получите лучшие результаты.....

Другие вопросы по тегам