Розробники на Java часто працюють з класами String
та StringBuilder
, але їх відмінності іноді можуть бути недооцінені. Якщо ви коли-небудь задавались питанням, чому перевірка equals
між String
і StringBuilder
не працює як очікується, ця стаття саме для вас. Давайте глибше розберемо ці основні концепти за допомогою практичних прикладів, щоб прояснити їх відмінності та те, як працює метод equals
для цих класів.
Строки в Java: Незмінні та Потужні
У Java String
— це незмінна послідовність символів. Незмінність означає, що після створення об'єкта String
його значення не можна змінити. Будь-яка операція, яка здається зміною String
, насправді створює новий об'єкт String
.
Що таке пул строк?
Пул строк — це спеціальна область пам'яті в хіпі Java, де зберігаються літерали рядків. Коли створюється літерал рядка, Java перевіряє пул, щоб подивитися, чи існує вже еквівалентний рядок. Якщо так, повертається посилання на існуючий рядок. Цей механізм допомагає оптимізувати використання пам'яті та підвищує продуктивність.
Приклад:
public class StringPoolExample {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2); // Вивід: true
}
}
Тут і str1
, і str2
вказують на один і той самий об'єкт у пулі рядків. Однак, якщо ви створите String
за допомогою ключового слова new
, він не використовуватиме пул.
Приклад:
public class NewStringExample {
public static void main(String[] args) {
String str1 = new String("Hello");
String str2 = "Hello";
System.out.println(str1 == str2); // Вивід: false
}
}
У цьому випадку str1
посилається на новий об'єкт у хіпі, тоді як str2
посилається на літерал у пулі.
Приклад незмінності:
public class StringExample {
public static void main(String[] args) {
String str = "Hello";
str = str + " World";
System.out.println(str); // Вивід: Hello World
}
}
Тут оригінальний "Hello"
залишается незмінним. Створюється новий об'єкт String
, "Hello World"
, і присвоюється змінній str
.
StringBuilder: Змінний та Ефективний
StringBuilder
— це змінна послідовність символів. Він розроблений для сценаріїв, коли потрібно часто змінювати рядки, оскільки він уникає витрат на створення нових об'єктів.
Приклад:
public class StringBuilderExample {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
System.out.println(sb); // Вивід: Hello World
}
}
Тут метод append
змінює той самий об'єкт StringBuilder
, що робить його більш ефективним за пам'яттю для повторюваних операцій.
Ключові відмінності між String і StringBuilder
Метод Equals: Як він працює
Метод equals
в Java використовується для порівняння двох об'єктів на рівність. Його поведінка відрізняється між String
і StringBuilder
.
1. Метод equals
класу String
Метод equals
в класі String
порівнює вміст двох рядків.
Приклад:
public class StringEquals {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1.equals(str2)); // Вивід: true
}
}
Хоча str1
і str2
є різними об'єктами, їх вміст однаковий, тому метод equals
повертає true
.
2. Метод equals
класу StringBuilder
Метод equals
в StringBuilder
не порівнює вміст.
Натомість він успадковує реалізацію класу Object
, яка перевіряє рівність посилань.
Приклад:
public class StringBuilderEquals {
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder("Hello");
StringBuilder sb2 = new StringBuilder("Hello");
System.out.println(sb1.equals(sb2)); // Вивід: false
}
}
Тут sb1
та sb2
мають однаковий вміст, але це різні об'єкти, тому метод equals
повертає false
.
Порівняння String з StringBuilder
Якщо ви спробуєте порівняти String
та StringBuilder
за допомогою методу equals
, результат завжди буде false
. Це відбувається тому, що метод equals
не виконує перетворення типів або порівняння вмісту між цими типами.
Приклад:
public class StringAndStringBuilderComparison {
public static void main(String[] args) {
String str = "Hello";
StringBuilder sb = new StringBuilder("Hello");
System.out.println(str.equals(sb)); // Вивід: false
}
}
Щоб порівняти їхній вміст, спочатку потрібно перетворити StringBuilder
у String
.
Правильне порівняння:
public class CorrectComparison {
public static void main(String[] args) {
String str = "Hello";
StringBuilder sb = new StringBuilder("Hello");
System.out.println(str.equals(sb.toString())); // Вивід: true
}
}
Основні висновки
Незмінність vs. Змінність:
String
незмінний, а StringBuilder
змінний.
Поведение методу Equals:
String.equals
порівнює вміст.StringBuilder.equals
перевіряє рівність посилань.
Оптимізація пулу рядків:
Рядки, створені як літерали, зберігаються в пулі рядків для оптимізації використання пам'яті.
Порівняння між типами:
Щоб порівняти String
з StringBuilder
, спочатку перетворіть StringBuilder
в String
.
Підсумки
Розуміння відмінностей між String
та StringBuilder
є важливим для написання ефективного та безпомилкового коду на Java. Незмінність String
робить його ідеальним для фіксованих значень, в той час як змінність StringBuilder
робить його чудовим для динамічних операцій. І коли справа доходить до equals
, завжди пам'ятайте про специфічну поведінку для кожного типу, щоб уникнути несподіванок.
Більше про String, StringBuilder та StringBuffer в цій статті: https://medium.com/@poojaauma/java-strings-string-stringbuilder-and-stringbuffer-comparison-8041553a7790
Перекладено з: String vs. StringBuilder: Why Your Equals Check Might Be Wrong (and What the String Pool Has to Do With It)