This is a nice article, который описывает две причины, уже упомянутые выше по ответам:
- безопасность: система может раздать чувствительные биты только для чтения информации, не беспокоясь, что они будут изменены
- Производительность: неизменные данные очень полезны в создании вещей поточно- ,
И это, вероятно, самый подробный комментарий в этой статье. Это связано с пулом строк в Java и проблемами безопасности. О том, как решить, что входит в пул строк. Предполагая, что обе строки равны, если их последовательность символов одинакова, тогда у нас есть условие гонки, кто первым попадает туда и вместе с ним проблемы с безопасностью. Если нет, то пул строк будет содержать избыточные строки, тем самым теряя преимущество наличия в первую очередь. Просто прочитайте это для себя, да?
Расширение Строка будет играть хаос с равными и стажером. JavaDoc говорит равен:
Сравнивает эту строку с указанным объектом.Результат является истинным тогда и только тогда, когда аргумент не является нулевым и является объектом String, который представляет ту же последовательность символов, что и этот объект.
Предполагая, что java.lang.String
не был окончательным, a SafeString
мог равняться String
, и наоборот; потому что они будут представлять одну и ту же последовательность символов.
Что произойдет, если вы примените intern
к SafeString
- будет ли SafeString
войти в пул строк JVM? ClassLoader
и все объекты, на которые ссылаются SafeString
, затем будут заблокированы на время существования JVM. Вы получите условие гонки, которое может быть первым, кто ставит последовательность символов - может быть, ваш SafeString
победит, может быть, String
или, может быть, SafeString
, загруженный другим загрузчиком классов (таким образом, другой класс).
Если вы выиграли гонку в пул, это будет настоящий синглтон, и люди смогут получить доступ ко всей вашей среде (песочнице) через отражение и secretKey.intern().getClass().getClassLoader()
.
Или JVM может заблокировать это отверстие, убедившись, что в пул добавлены только конкретные объекты String (и никакие подклассы).
Если равно была реализована таким образом, что SafeString
! = String
то SafeString.intern
! = String.intern
и SafeString
должны быть добавлены к бассейну. Тогда пул станет пулом <Class, String>
вместо <String>
, и все, что вам нужно будет ввести в пул, будет новым загрузчиком классов.
Спасибо всем за ваши ответы, особенно TrueWill, Бруно Рейс и Тило! Мне жаль, что я не мог выбрать более одного ответа, но, к сожалению, ...! – Alex
Также рассмотрите распространение «О, мне просто нужны еще несколько методов утилиты на String», которые будут всплывать, - все из которых не могли использовать друг друга, потому что они были другим классом. –
Спасибо за этот ответ, очень полезный. теперь у нас есть два факта. Строка - это конечный класс & его неизменный, потому что он не может быть изменен, но может быть передан другому объекту. но как насчет: - String a = new String ("test1"); тогда s = "test2"; Если String - это объект класса Final, то как его можно изменить? Как я могу использовать модифицированный конечный объект. Пожалуйста, позвольте мне, если я ошибочно спросил что-нибудь. –