Подтвердить что ты не робот

Java неизменяемые классы?

Я нашел статью с интересным фрагментом кода:

public class Employee {

    private String firstName;
    private String lastName;

    //private default constructor
    private Employee(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public static Employee valueOf (String firstName, String lastName) {
        return new Employee(firstName, lastName);
    }
}

Мне действительно интересно узнать о преимуществах создания таких классов. Я понимаю, что здесь объект этого класса был бы неизменным, потому что нет возможности изменить его значения переменных после инициализации. Раньше я никогда ничего подобного не делал, и я действительно не понимаю его преимущества.

  • Почему это хорошая практика?
  • Не могли бы вы назвать ситуацию, когда этот подход можно использовать?
  • Как насчет констант или переменных только для чтения? Разве это не очень похоже?
  • В статье говорится, что это плохо для производительности приложения. Но почему?
4b9b3361

Ответ 1

Пример, который вы упомянули, относится к Неизменяемым объектам. Его широко используемые понятия в языках программирования.

Цитата из ссылки выше. Преимущества

  • просты в построении, тестировании и использовании
  • автоматически потокобезопасны и не имеют проблем с синхронизацией.
  • не нужен конструктор копирования
  • не нужна реализация клона
  • разрешить hashCode использовать ленивую инициализацию и кэшировать возвращаемое значение
  • не нужно копировать защитно при использовании в качестве поля
  • сделать хорошие клавиши карты и установить элементы (эти объекты не должны меняться в то время как в коллекции)
  • имеют свой классовый инвариант, установленный один раз при построении, и его никогда не нужно проверять снова
  • всегда имеет "атомарность отказа" (термин, используемый Джошуа Блохом): если неизменный объект - генерирует исключение, он никогда не покидает нежелательное или неопределенное состояние.

Ответ 2

Неизменяемые классы:

  • поточно-безопасный по умолчанию (одновременная запись никогда не возникает)
  • кэшировать

Вы можете много узнать о них в контексте языка Java в Эффективная Java.

Ответ 3

Основным преимуществом неизменяемых классов является безопасность потоков. Большинство проблем с потоками происходят из общего, изменчивого состояния. Делая объекты неизменными, гораздо легче рассуждать о них, особенно в многопоточных средах.

В статье говорится, что "создание неизменяемых объектов может повлиять на производительность приложения". Я не знаю, почему это сказано. Это совершенно неправильно. Нет ничего неотъемлемого в неизменяемых объектах, которые могут повлиять на производительность приложения.

Ответ 4

-Почему это хорошая практика?

Потому что вы можете пройти класс вокруг и быть уверенным, что он никогда не будет изменен кодом "изгоев". То же самое для Java Strings, они неизменяемы.

-Вы можете назвать ситуацию, когда этот подход может быть использован?

Это очень полезно в больших проектах, где много команд работают вместе или при разработке фреймворка или API. В таких ситуациях, поскольку вы не отвечаете за части кода, вы никогда не сможете доверять тому, что объект, который вы передаете другим частям кода, не будет изменен. Используйте неизменяемость, если вам нужно убедиться, что объект не будет изменен.

-Что насчет констант или переменных только для чтения? Разве это не очень похоже?

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

- В статье говорится, что это плохо для производительности приложения. Но почему?

Поскольку каждый раз, когда вам нужно изменить объект, вам нужно создать новые экземпляры. То же самое для строк, вы не можете сделать myString.append("42"), вам нужно сделать myString = myString+"42", который создает новый объект String.

Ответ 5

Если вы используете хеш-таблицы, наличие неизменяемых объектов является хорошим, потому что вам не нужно пересчитывать хэш-код при изменении состояния объекта (поскольку они неизменяемы).

Ответ 6

В статье говорится:

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

Собственно, это неправильно. Эти две концепции на самом деле не связаны.

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

Или вы можете передать измененный объект в качестве параметра методу factory или объявить метод мутатора

- > Сотрудник будет изменен, хотя вы используете метод factory и частный конструктор.

Ответ 7

В данном примере он делает конструктор закрытым и, таким образом, напрямую контролирует создание объекта извне.

Значение: Поскольку конструктор является закрытым, вы не можете делать

Employee e = new Employee("steve","jobs"); 

извне этого класса.

Таким образом, программист этого класса принимает управление объектом для этого класса.

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

Ответ на предыдущий вопрос прост, если вы создадите свой конструктор и сами создаете объекты для своего класса, когда захотите в статическом методе. Примечание. Статические методы могут быть доступны напрямую, используя имя класса.

Примечание. Такие шаблоны проектирования будут сильно использоваться в шаблонах проектирования singleton, для которых требуется только один объект для данного класса.