Це приємна стаття, яка викладає дві причини, про які вже йшлося у вищезазначених відповідях:
- Безпека : система може роздавати чутливі біти інформації лише для читання, не переживаючи, що вони будуть змінені
- Продуктивність : незмінні дані дуже корисні, щоб зробити речі безпечними.
І це, мабуть, найбільш детальний коментар у цій статті. Це стосується пулу рядків у Java та питань безпеки. Це про те, як вирішити, що йде в пуловий рядок. Якщо припустити, що обидва рядки рівні, якщо їх послідовність символів однакова, то ми маємо умову перегону щодо того, хто потрапить туди першим, а також разом із ним і питання безпеки. Якщо ні, то пуловий рядок міститиме надлишкові рядки, тим самим втрачаючи перевагу в першу чергу. Просто прочитайте це для себе, чи не так?
Розширення String зіграло б хаос з рівними та стажистами. JavaDoc каже, що дорівнює:
Порівняє цей рядок із заданим об'єктом. Результат вірний, якщо і тільки якщо аргумент не є нульовим і є об'єктом String, який представляє ту саму послідовність символів, що і цей об'єкт.
Якщо припустити, що java.lang.String
не було остаточним, а SafeString
може бути рівним a String
, і навпаки; тому що вони представляли б ту саму послідовність символів.
Що буде, якби ви звернулися intern
до a SafeString
- чи SafeString
перейшов би в рядок рядків JVM? Потім ClassLoader
і всі об'єкти, на SafeString
які посилаються, були заблоковані на протязі життя СВМ. Ви отримаєте перегони про те, хто може бути першим, хто пройшов стажування послідовності символів - можливо, ваш SafeString
переможе, може бути String
, а може бути SafeString
завантажений іншим завантажувачем класів (таким чином, іншим класом).
Якщо ви виграли гонку в басейн, це був би справжній сингл, і люди могли отримати доступ до всього вашого середовища (пісочниці) за допомогою роздумів і secretKey.intern().getClass().getClassLoader()
.
Або JVM міг перекрити цю дірку, переконавшись, що до пулу додано лише конкретні об'єкти String (а не підкласи).
Якщо рівне було реалізовано таким, що SafeString
! = String
Тоді SafeString.intern
! = String.intern
, І SafeString
його потрібно було б додати до пулу. Тоді пул <Class, String>
замість цього стане пулом, <String>
і все, що вам потрібно буде ввійти в басейн, буде новим завантажувачем класів.