Як порівнювати рядки в Java?
У своїй програмі я використовував оператор ==
для порівняння рядків. Але я натрапив на баг, і при заміні ==
на equals
він пропав.
Слід уникати оператора ==
? Коли його можна використовувати, а коли ні? В чому різниця?
Відповіді на питання (1)
Оператор ==
порівнює посилання.
Метод equals
порівнює значення.
Отже, якщо ви хочете порівняти рядки на рівність, слід використовувати equals
.
Однак в деяких випадках рядки гарантовано представлені одним і тим же об'єктом завдяки пулу рядків (string interning). Ці випадки явно описані в специфікації мови Java .
Оператор ==
використовується для перевірки, що два рядки вказують на один і той же об'єкт.
// Ці рядки мають одне і те саме значення
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
// Рядки з пулу можуть буди отримані за допомогою виклику intern().
"test" == "!test".substring(1).intern() // --> true
Треба відзначити, що ==
помітно швидше, ніж equals
(порівняння посилання замість виклику методу і посимвольного порівняння, якщо рядки різної довжини), тому, якщо ви працюєте з рядками з пулу (або системного, або свого), заміна equals
на ==
може привести до помітного прискорення. Але це трапляється дуже рідко.
Остерігайтеся виклику equals
на null
! Оператор ==
прекрасно порівнює рядки, якщо один або більше з них дорівнює null
, але виклик методу equals
на рядок, що дорівнює null
, призведе до виключення.
Для порівняння рядків, які можуть бути рівні null, ви можете скористатися наступним методом:
public static boolean equals(String str1, String str2) {
return str1 == null ? str2 == null : str1.equals(str2);
}
Він присутній в деяких сторонніх бібліотеках, наприклад, в Apache Commons.
Якщо ви користуєтеся сучасними середовищами розробки, то вони попередять, якщо ви спробуєте порівняти рядки за допомогою оператора ==
. Завжди звертайте увагу на подібні попередження.