В чем разница между объявлением строки и объявлением ее как финальной? - PullRequest
1 голос
/ 25 февраля 2012

Я знаю, что строки неизменны.

Тогда какая разница между:

String name ="Name";
final String name ="Name";

Почему мы используем final в этом контексте? Поскольку String уже неизменен, в этом нет необходимости. Второй связанный вопрос, почему String's immutable ?. Другие типы данных, такие как int, логические не являются. Если String является неизменным, это делает его потокобезопасным? Я прочитал, что "если бы String был изменяемым, запрос на загрузку" java.io.Writer "мог бы быть изменен на" mil.vogoon.DiskErasingWriter "" means?

Ответы [ 6 ]

4 голосов
/ 25 февраля 2012

Здесь много вопросов, но вот несколько заметок, которые должны ответить на большинство из них:

  • final означает, что переменная может быть назначена только один раз. Это не имеет ничего общего с изменчивостью, которая является свойством объекта, а не переменной (которая является просто дескриптором)
  • String является неизменным, потому что вы не можете изменить его внутреннее состояние (у него есть private char[] chars, который содержит символы). Примитивы также неизменны. Это лучше видно в их эквивалентах - Integer, Long и т. Д.
  • да, строка является поточно-ориентированной, поскольку ее состояние нельзя изменить независимо от того, сколько потоков с ней работает. Каждая операция со строкой приводит к новому экземпляру, а не к изменению существующего.
2 голосов
/ 25 февраля 2012

Я прочитал, что "если бы String был изменяемым, запрос на загрузку" java.io.Writer "мог бы быть изменен на" mil.vogoon.DiskErasingWriter ""

OK,Первое, что нужно понять, это то, что это гипотетическая дискуссия.Строка не является изменяемой.

Итак, представьте себе этот фрагмент кода:

public static final String CLASS_NAME = "java.io.Writer";

...

Class<?> clazz = Class.forName(CLASS);

Какой класс это на самом деле загружает?

Если строки являются изменяемыми, выполняется какой-то гнусный кодв изолированной программной среде безопасности сможет изменить содержимое объекта String, на которое ссылается CLASS_NAME.В частности, он может изменить его с «java.io.Writer» на «mil.vogoon.DiskErasingWriter».Конечным результатом является то, что ваше приложение будет обманом загружено в неправильный класс.

Делая String неизменным типом (и одной или двумя другими вещами), этот механизм атаки не работает.

2 голосов
/ 25 февраля 2012

final означает, что вы не можете присвоить переменной новое значение.

String name = "Name";
name = "MyName"; // legal

final String name = "Name";
name = "MyName"; // illegal, compiler error

Вот статья о том, почему строки неизменны:

http://javarevisited.blogspot.com/2010/10/why-string-is-immutable-in-java.html

1 голос
/ 25 февраля 2012

Это разница между объектом и его ссылкой. Переменной final можно присвоить значение только один раз. Это верно независимо от того, ссылается ли переменная на неизменный объект или нет.

Обратите внимание, что «неизменяемый» объект обычно (но не обязательно) состоит из наборов final ссылок.

1 голос
/ 25 февраля 2012

Как сказал Уильям:

final означает, что вы не можете присвоить переменной новое значение.

Кроме того, если вы играете с анонимным внутренним классом, например:

final String mystring = "Hello";
button.addClickHandler(new ClickHandler() {
    void click() {
        System.out.println(mystring);
    }
});

Объект mystring должен быть конечным.

0 голосов
/ 25 февраля 2012

На другие пункты уже дан ответ, но вы все еще ищете объяснение той цитате, которую вы нашли:

, если строка изменяемая, запрос на загрузку java.io.Writer"мог быть изменен для загрузки" mil.vogoon.DiskErasingWriter "

Для справки, это, кажется, из другого SO-ответа, который является несколько коротким и не учитывает детали.

В общем, если вы пишете открытый класс, который принимает изменяемые объекты и сохраняет их или возвращает изменяемый объект, который он хранит, вызывающий код может изменить этот объект из-под ног этого класса.

Дляпример.Отказ от ответственности: я не знаю много о ClassLoader, так что это просто для иллюстрации проблемы.ClassLoader имеет функцию loadClass(String name).Представьте, что метод сначала проверяет, является ли класс с таким именем допустимым или доверенным, а затем загружает его.Теперь, если String был изменяемым, вызывающий код мог изменить имя класса из-под ног загрузчика классов после того, как он уже проверил класс, и, таким образом, обойти меры безопасности.

Конечно, если String был изменяемым, можно было бынадеюсь, что реализация ClassLoader сначала создаст защитную копию строки.Таким образом, вызывающий код не имеет возможности обойти защиту, поскольку у него нет возможности изменить содержимое copy .Это общее правило: не позволяйте вызывающему коду иметь какой-либо дескриптор изменяемых внутренних данных вашего класса.

Так что String не должен быть неизменяемым для обеспечения безопасной загрузки класса.Однако с неизменяемыми объектами легче обеспечить безопасность такого рода, поскольку их просто нельзя изменить из-под вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...