String.equals против ==
Заголовок: Проблема с сравнением строк в Java
Я пытаюсь разделить строку на токены и сохранить их в массив строк. После этого я сравниваю переменную с первым элементом массива, но почему-то это не работает. Вот мой код:
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");
}
}
Проблема в том, что сравнение строк с помощью оператора ==
не дает ожидаемого результата. Я ожидал, что при выполнении условия if ((datos[0] == usuario))
на консоли должно было появиться сообщение "WORKING". Однако этого не происходит. В чем может быть причина? Как правильно сравнивать строки в Java?
5 ответ(ов)
Вместо
datos[0] == usuario
используйте
datos[0].equals(usuario)
Оператор ==
сравнивает ссылки на объекты, в то время как метод .equals()
сравнивает значения, что в данном случае является тем, что вам нужно.
Функция equals()
является методом класса Object
, который разработчик должен переопределить. Класс String
переопределяет его для проверки, равны ли две строки, т.е. имеют ли они одинаковое содержимое, а не являются ли они одним и тем же объектом в памяти.
Оператор ==
проверяет, ссылаются ли обе переменные на один и тот же объект.
Рассмотрим следующие примеры программ:
String abc = "Awesome";
String xyz = abc;
if (abc == xyz)
System.out.println("Указывают на одну и ту же строку");
Здесь переменные abc
и xyz
ссылаются на одну и ту же строку "Awesome"
. Поэтому выражение (abc == xyz)
возвращает true
.
String abc = "Hello World";
String xyz = "Hello World";
if (abc == xyz)
System.out.println("Указывают на одну и ту же строку");
else
System.out.println("Указывают на разные строки");
if (abc.equals(xyz))
System.out.println("Содержимое обеих строк одинаково");
else
System.out.println("Содержимое строк различается");
В этом примере abc
и xyz
— это две разные строки с одинаковым содержимым "Hello World"
. Следовательно, выражение (abc == xyz)
возвращает false
, а (abc.equals(xyz))
— true
.
Надеюсь, теперь вы понимаете разницу между ==
и <Object>.equals()
.
Спасибо.
Оператор ==
проверяет, указывают ли две ссылки на один и тот же объект или нет. Метод .equals()
проверяет фактическое содержимое строк (значение).
Обратите внимание, что метод .equals()
принадлежит классу Object
(суперклассу всех классов). Вам необходимо переопределить его в соответствии с требованиями вашего класса, однако для строки он уже реализован и проверяет, имеют ли две строки одинаковое значение.
Пример 1)
String s1 = "Stack Overflow";
String s2 = "Stack Overflow";
s1 == s1; // true
s1.equals(s2); // true
Причина: Строковые литералы, созданные без null, хранятся в пуле строк в области перманентной памяти кучи. Поэтому как s1, так и s2 указывают на один и тот же объект в пуле.
Пример 2)
String s1 = new String("Stack Overflow");
String s2 = new String("Stack Overflow");
s1 == s2; // false
s1.equals(s2); // true
Причина: Если вы создаете объект String с помощью ключевого слова `new`, ему выделяется отдельное пространство в куче.
==
проверяет равенство ссылок.
.equals()
проверяет равенство значений.
Следовательно, если вы хотите проверить, имеют ли две строки одно и то же значение, вам следует использовать .equals()
(за исключением некоторых случаев, когда вы можете гарантировать, что две строки с одинаковым значением будут представлены одним и тем же объектом, например, при интернировании строк).
==
нужно использовать для проверки, являются ли две строки одним и тем же объектом Object
.
// Эти две строки имеют одинаковое значение
new String("test").equals("test") ==> true
// ... но они не являются одним и тем же объектом
new String("test") == "test" ==> false
// ... и эти не равны
new String("test") == new String("test") ==> false
// ... а эти равны, потому что литералы интернируются компилятором и
// таким образом ссылаются на один и тот же объект
"test" == "test" ==> true
// Конкатенация строковых литералов происходит на этапе компиляции, что также приводит к одним и тем же объектам
"test" == "te" + "st" ==> true
// Но .substring() вызывается во время выполнения, создавая отдельные объекты
"test" == "!test".substring(1) ==> false
Важно отметить, что ==
значительно дешевле, чем .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 to str2
str3 != str4
str3 equals to str4
Как преобразовать строку в int в Java?
Преобразование 'ArrayList<String>' в 'String[]' в Java
Как сгенерировать случайную алфавитно-цифровую строку
Как преобразовать символ в строку?
Как преобразовать строку Java в byte[]?