Почему класс String объявлен финальным в Java?

С тех пор, как я узнал, что класс java.lang.String объявлен как финальный в Java, мне стало интересно, почему это так. Тогда я не нашел никакого ответа, но этот пост: Как создать реплику класса String в Java? напомнил мне о моем запросе.

Конечно, String предоставляет всю необходимую мне функциональность, и я никогда не думал о какой-либо операции, которая потребовала бы расширения класса String, но, тем не менее, вы никогда не узнаете, что кому-то может понадобиться!

Итак, кто-нибудь знает, каково было намерение дизайнеров, когда они решили сделать его окончательным?

134
задан Boann 20 March 2019 в 19:28
поделиться

6 ответов

Спасибо за оба ответа. Я объединил оба ваших ответа в одно... свойство с таким фильтром:

 def _get_blue_shirts(self):
  if self.shirtclr.filter(shirtcolor='Blue'):
   return '%s%s' % ('B', self.shirtmodel)
  else:
   return self.shirtmodel
 blue_shirts=property(_get_blue_shirts)

Хотя этот подход определенно работает, я вижу проблемы с ним, как я написал его. Во-первых, я хотел бы найти в admin с, например, «B13A» в качестве модели рубашки и понять, что я имею в виду «13A» рубашка доступна с Blue в качестве одного из его цветов. Поскольку ModelAdmin.search_fields, по-видимому, необходимо перейти к фактическому полю, этот подход не работает в этом отношении (исправьте меня, если я там не прав). Другая проблема, которую я имею, заключается в том, что свойство кажется очень тяжелым для SQL... выполнение отдельного выбора для каждой строки (в то время как выделенному столбцу просто нужен общий выбор... снова, исправьте меня, если я не прав). Есть идеи, как я могу решить эти проблемы? Возможно, я мог бы пойти по этому пути?

PS. Энтони... Я попробовал переработанный переопределенный save () и все еще получил экземпляр "" ShirtClass "" должен иметь значение первичного ключа, прежде чем отношение "многие ко многим" может быть использовано "ошибка. Я делаю что-то не так здесь?

Многие, многие, большое спасибо всем, -bkev

-121--4196174-

Это не должно занять столько времени.

Одно дело - очистить список последних файлов.

ALT + x recentf-cleanup

Другое дело, чтобы убедиться, что ваш файл .emacs только что скомпилирован, если вы изменили даже один или два символа, то Emacs увидит, что ваш файл .emacs новее скомпилированной версии и он не будет использовать скомпилированную версию.

Выполните следующее:

ALT + x byte-compile-file

Затем перейдите к файлу .emacs и нажмите Enter, чтобы создать файл с именем .emacs.elc

Emacs будет использовать .emacs.elc, если он не старше вашего файла .emacs

-121--3926492-

Очень полезно иметь последовательности, реализованные как неизменяемые объекты . Вы должны прочитать о неизменяемости , чтобы понять больше об этом.

Одно из преимуществ неизменяемых объектов состоит в том, что

дубликаты можно совместно использовать, указывая их на один экземпляр.

(от здесь ).

Если последовательность не были окончательными, можно создать подкласс и иметь два ряды, похожие на «видимые как последовательности», но фактически отличающиеся друг от друга.

86
ответ дан 23 November 2019 в 23:56
поделиться

String - это очень основной класс в Java, многие вещи полагаются на него, работают определенным образом, например, неизменным.

Создание класса Final предотвращает подклассы, которые могут нарушить эти предположения.

Обратите внимание, что даже сейчас, если вы используете отражение , вы можете сломать строки (измените их значение или hashcode). Отражение может быть остановлено с помощью менеджера безопасности. Если строка не было финала , каждый мог это сделать.

Другие классы, которые не объявлены Финал позволяют определить несколько сломанные подклассы (вы могли бы иметь список , который добавляет к неправильному положению, например), но, по крайней мере, JVM не зависит от тех, которые для его основных операций.

15
ответ дан 23 November 2019 в 23:56
поделиться

Возможно, это было упростить реализацию. Если вы разработаете класс, который будет наследственным пользователям класса, то у вас есть совершенно новый набор случаев использования, чтобы учитывать ваш дизайн. Что произойдет, если они сделают это или что с X предпринимаемым полем? Делать его окончательным, они могут сосредоточиться на правильной работе общедоступного интерфейса, и убедитесь, что это твердое.

2
ответ дан 23 November 2019 в 23:56
поделиться

Это хорошая статья , которая описывает две причины, уже упомянутые в ответах на вышеприведенные вопросы:

  1. Безопасность: система может раздавать чувствительные биты только для чтения информация, не беспокоясь о том, что они будут изменены
  2. Performance: неизменяемые данные - очень полезен для того, чтобы сделать вещи нитевидными.

И это, пожалуй, самый подробный комментарий в этой статье. Он касается пула строк в Java и вопросов безопасности. Он о том, как решить, что попадает в строковый пул. Если предположить, что обе строки равны, если их последовательность символов одинакова, то у нас есть условие гонки на то, кто попадет туда первым, и вместе с этим проблемы безопасности. Если нет, то пул строк будет содержать лишние строки, теряя тем самым преимущество. Просто прочитайте это для себя, ладно?


Расширение струн будет играть хаос с равными и интернами. JavaDoc говорит equals:

Сравнивает эту строку с указанным объектом. Результат верен, если и только если аргумент не равен нулю и является объектом String, который представляет ту же самую последовательность символов, что и объект this.

Если предположить, что java.lang.String не является окончательным, то SafeString может быть равен String, и наоборот; потому что они будут представлять ту же самую последовательность символов.

Что произойдет, если применить intern к SafeString -- пойдет ли SafeString в пул строк JVM? КлассLoader ClassLoader и все объекты, на которые ссылается SafeString, будут заблокированы на время жизни JVM. Вы получите состояние гонки о том, кто может первым вставить последовательность символов -- может быть ваш SafeString выиграет, может быть String, или может быть SafeString загруженный другим классом загрузчика (таким образом другим классом).

Если бы вы выиграли гонку в пул, это был бы настоящий singleton, и люди могли бы получить доступ ко всему окружению (песочнице) через отражение и secretKey.intern().getClass().getClassLoader().

Или JVM мог заблокировать эту дыру, убедившись, что в пул были добавлены только конкретные объекты String (и никаких подклассов).

Если бы равные были реализованы так, что SafeString != String, то SafeString.intern != String.intern, и SafeString должны были бы быть добавлены в пул. Затем пул станет пулом вместо , и все, что вам нужно, чтобы войти в пул, будет свежим загрузчиком классов.

59
ответ дан 23 November 2019 в 23:56
поделиться

Как сказал Бруно, это о неизменности. Это не только о струнах, но и о любых обертках E.g. Двойной, целочисленные, характер и т. Д. Есть много причин для этого:

  • Безопасность потоков
  • Безопасность
  • Куча, которая управляется самой java (по-разному для обычной кучи, который является собранным по-разному)
  • Управление памятью

в основном это, так что вы, как программист, могут быть уверены, что ваша строка никогда не будет изменена. Это также, если вы знаете, как это работает, может улучшить менеджер памяти. Попробуйте создать две идентичные строки один за другим, например, «Hello». Вы заметите, если вы отладки, что у них есть идентичные идентификаторы, это означает, что они точно такие же объекты. Это связано с тем, что Java давайте сделаем это. Это не было бы возможно, если струны были исправлены. Они могут иметь то же самое, что я и т. Д., потому что они никогда не изменится. Поэтому, если вы когда-нибудь решите создать 1 000 000 строк «Hello», что вы действительно сделаете, это создать 1 000 000 указателей на «Hello». Помимо любая функция на строке или любые обертки по этой причине, приведет к созданию другого объекта (снова посмотрите на идентификатор объекта - он изменится).

Плитингово финал в Java не обязательно не обязательно означает, что объект не может измениться (он отличается для примера C ++). Это означает, что адрес, к которому он точки не может измениться, но вы все равно можете изменить его свойства и / или атрибуты. Поэтому понимание разницы между неизменностью и финалом в некоторых случаях может быть действительно важным.

HTH

Список литературы:

6
ответ дан 23 November 2019 в 23:56
поделиться

В дополнение к причинам, указанным в других ответах (безопасность, неизменяемость, производительность), следует отметить, что String имеет специальную языковую поддержку. Вы можете писать литералы String , и есть поддержка оператора + . Разрешение программистам создавать подклассы String будет способствовать взлому, например:

class MyComplex extends String { ... }

MyComplex a = new MyComplex("5+3i");
MyComplex b = new MyComplex("7+4i");
MyComplex c = new MyComplex(a + b);   // would work since a and b are strings,
                                      // and a string + a string is a string.
2
ответ дан 23 November 2019 в 23:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: