Ми не можемо бути впевнені, що насправді думали дизайнери Java під час проектування, String
але ми можемо зробити висновки лише про ці причини, виходячи з тих переваг, які ми отримуємо від непорушності рядків, деякі з яких:
1. Існування струнного постійного басейну
Як обговорювалося в статті Чому String зберігається в String Constant Pool , кожна програма створює занадто багато рядкових об'єктів і для того, щоб врятувати JVM спочатку створюючи багато рядкових об'єктів, а потім збираючи їх сміттям. JVM зберігає всі рядкові об'єкти в окремій області пам’яті під назвою String постійний пул і повторно використовує об’єкти з цього кешованого пулу.
Щоразу, коли ми створюємо літеральний рядок, JVM вперше бачить, чи є цей літерал вже присутній у постійному пулі чи ні, і якщо він є, нова посилання почне вказувати на той самий об’єкт у SCP.
String a = "Naresh";
String b = "Naresh";
String c = "Naresh";
У наведеному вище прикладі рядки об'єкта зі значенням Naresh
отримає створений в SCP тільки один раз , і всі посилання a
, b
, c
буде вказувати на той самий об'єкт , але що , якщо ми спробуємо внести зміни в a
наприклад a.replace("a", "")
.
В ідеалі, a
має мати значення , Nresh
але b
, c
має залишатися незмінним , оскільки в якості кінцевого користувача ми робимо зміни в a
тільки. І ми знаємо a
, b
, c
всі вони вказують на той самий об'єкт , так що якщо ми робимо зміни a
, інші повинні також відображати зміни.
Але незмінність рядків рятує нас від цього сценарію, і завдяки незмінюваності об'єкта string рядковий об'єкт Naresh
ніколи не зміниться. Отже, коли ми робимо будь-яку зміну a
замість зміни об'єкта рядка, Naresh
JVM створює новий об'єкт, присвоює йому a
і потім вносить зміни в цей об'єкт.
Таким чином, String пул можливий лише через незмінність String, і якщо String не був би незмінним, кешування рядкових об'єктів та повторне їх використання не мали б можливості, оскільки будь-яка змінна змінює значення та пошкоджує інші.
І тому цим JVM обробляє дуже спеціально і йому надається особлива область пам’яті.
2. Безпека нитки
Об'єкт називається безпечним для потоків, коли на ньому працює кілька потоків, але жодна з них не може пошкодити його стан і утримувати однаковий стан для кожного потоку в будь-який момент часу.
Оскільки ми незмінний об'єкт не може бути модифікований ким-небудь після його створення, що робить кожен незмінний об'єкт потоком безпечним за замовчуванням. Нам не потрібно застосовувати до нього жодних заходів безпеки потоку, таких як створення синхронізованих методів.
Таким чином, завдяки своєму незмінному природному рядку об'єкт може бути розділений декількома потоками, і навіть якщо він маніпулює багатьма потоками, він не змінить свого значення.
3. Безпека
У кожній програмі нам потрібно передавати кілька секретів, наприклад, ім’я користувача \ паролі, URL-адреси підключення і взагалі вся ця інформація передається як об'єкт рядка.
Тепер припустімо, що якщо String не був би незмінним за своєю природою, це спричинило б серйозну загрозу безпеці програми, оскільки ці значення дозволяється змінювати, а якщо це дозволено, вони можуть бути змінені через неправильно написаний код або будь-яку іншу особу, яка мати доступ до наших змінних посилань.
4. Завантаження класу
Як обговорювалося в « Створення об’єктів через Reflection в Java з Example» , ми можемо використовувати Class.forName("class_name")
метод для завантаження класу в пам’ять, який знову викликає інші методи для цього. І навіть JVM використовує ці методи для завантаження класів.
Але якщо ви чітко бачите, що всі ці методи приймають ім'я класу як об'єкт рядка, тому Strings використовуються при завантаженні java-класу, а незмінність забезпечує безпеку, що завантажується правильний клас ClassLoader
.
Припустимо, якби String не був би незмінним, і ми намагаємося завантажити, java.lang.Object
які змінюються org.theft.OurObject
між ними, і тепер усі наші об'єкти мають поведінку, яку хтось може використовувати до небажаних речей.
5. Кешування HashCode
Якщо ми будемо виконувати будь-які операції, пов'язані з хешуваннями, на будь-якому об'єкті ми повинні перекрити hashCode()
метод і спробувати створити точний хеш-код, використовуючи стан об'єкта. Якщо стан об'єкта змінюється, це означає, що його хеш-код також повинен змінюватися.
Оскільки String є незмінним, тому значення, яке має один об'єкт рядка, ніколи не буде змінено, а значить, його хеш-код також не зміниться, що дає класу String можливість кешувати його хеш-код під час створення об'єкта.
Так, String об'єкт кешує свій хеш-код під час створення об’єкта, що робить його чудовим кандидатом для хеш-операцій, оскільки хеш-код не потрібно обчислювати знову, що економить нам час. Ось чому String використовується в основному як HashMap
клавіші.
Детальніше про те, чому струна є незмінною та остаточною на Java .