Альтернативный способ сделать класс неизменным - PullRequest
0 голосов
/ 23 февраля 2019

Я читал Эффективное Java Третье издание.Тема:

Пункт 17: Минимизировать мутабитность

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

Вот что написано в теме:

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

Я могу согласиться с тем, чтобы сделать конструктор приватным, это сделает класс не подклассифицированным.Но класс с закрытым конструктором пакета может быть вложен в подпакет.Так будет ли класс по-прежнему неизменным с помощью закрытого конструктора пакета?

Редактировать 1:

Класс с закрытым конструктором пакета по-прежнему неизменен для класса вне пакета.Но полезен ли этот подход?

Ответы [ 2 ]

0 голосов
/ 23 февраля 2019

Наличие частного конструктора пакета не гарантирует 100% неизменности, как уже упоминалось в комментарии:

В одном пакете можно создать изменяемый подкласс

Разрабатывая библиотеку jar, вы можете заключить некоторые соглашения внутри команды и сопровождающих пакетов, что из couse не реализует это программно, но все же каким-то образом находится под контролем разработчиков продукта.

А как насчет других?Можно создавать классы вне вашей библиотеки, но в одном и том же пакете и в нескольких местах в пути к классам.

Если у вас есть такие случаи и вы сталкиваетесь с подобными вопросами, в игру вступает Package Sealing .

Пакеты в файлах JAR могут быть опционально запечатаны, что означает, что все классы, определенные в этом пакете, должны быть заархивированы в одном и том же файле JAR.Возможно, вы захотите запечатать пакет, например, для обеспечения согласованности версий между классами в вашем программном обеспечении.

Если вы хотите гарантировать, что все классы в пакете происходят из одного и того же источника кода, используйте уплотнение JAR.Запечатанный JAR указывает, что все пакеты, определенные этим JAR, запечатаны, если они не переопределены для каждого пакета.

Допустим, у вашего jar libarary есть класс com.example.Factory с protected/package-private членамии пакет com.example запечатан.Попытка создания класса com.example.Accessor, который пытается получить доступ к этим членам, должна завершиться неудачей.

Таким образом вы можете обеспечить доступ к package-private членам ограниченной (и потенциально доверенной) группы членов.

Возвращаясь к основному вопросу:

Так будет ли класс по-прежнему неизменным с помощью приватного конструктора пакета?

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

0 голосов
/ 23 февраля 2019
public class BaseClass {
   private final String arg1;
   private final String arg2;

   public BaseClass(final String arg1, final String arg2) {
      this.arg1 = arg1;
      this.arg2 = arg2;
   }

   public String getArg1() { return arg1; }
   public String getArg2() { return arg2; }
}

Возможно создание подкласса этого класса, но всегда необходимо указывать значения для arg1 и arg2, и их нельзя изменить.Очевидно, что подклассом его можно переопределить два getter метода.

Мой подход, позволяющий избежать возможных ошибок со стороны меня и коллег, заключается в программировании на interface (s).

public interface BaseInterface {
   String arg1();
   String arg2();
}

Использование этого интерфейса повсеместно в кодовой базе обеспечит уменьшение количества ошибок, поскольку внутреннее состояние может быть изменено только в точке создания.Как только объект покидает точку создания, он больше не может быть изменен (вполне возможно, но вы должны вручную уменьшить его, и это легко заметить).


Другая стратегия, позволяющая избежать создания подклассов (и, возможно, изменчивость) использует процессоры аннотаций.Это обеспечит соблюдение вашего правила во время компиляции.

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