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

Неизменяемый тип: публичные конечные поля против геттера

Мне нужен небольшой контейнер-класс для хранения некоторых строк, которые должны быть неизменными. Поскольку сама строка является неизменным типом, я подумал о чем-то подобном:

public final class Immu
{
  public final String foo;
  public final String bar;

  public Immu(final String foo, final String bar)
  {
    this.foo = foo;
    this.bar = bar;
  }
}

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

Другие мысли, которые я могу пропустить на этом?

4b9b3361

Ответ 1

Я сделал бы то, что вы считаете самым простым и ясным. Если у вас есть класс значений данных, который используется только ограниченным числом классов. esp пакетный класс пакета. то я бы избегал getter/seters и использовал локальные или публичные поля пакета.

Если у вас есть класс, который вы ожидаете от использования другими модулями/разработчиками, то после использования модели getter/setter может быть более безопасный подход в долгосрочной перспективе.

Ответ 2

Проблема заключается в принципе единого доступа. Впоследствии вам может потребоваться изменить foo так, чтобы он был получен с помощью метода вместо фиксированного, и если вы выставили поле вместо получателя, вам нужно будет разбить ваш API.

Ответ 3

Этот ответ устранен:

Почему бы и нет

interface Immu { String getA() ; String getB ( ) }

Immu immu ( final String a , final String b )
{
       /* validation of a and b */
       return new Immu ( )
       {
              public String getA ( ) { return a ; }

              public String getB ( ) { return b ; }
       }
}

Ответ 4

Я использую шаблон public-final-field (anti?) для домашних проектов для классов, которые в основном представляют собой неизменяемую структуру данных с конструктором, а также абсолютные основы, такие как equals(), hashCode(), toString() и т.д.. если необходимо. (Я избегаю слова "struct" из-за различных интерпретаций его языка.)

Я бы не применил этот подход к кому-то еще кодовой базе (работа, публичный проект и т.д.), потому что это, вероятно, будет несовместимо с другим кодом, и такие принципы, как When In Rome или Lessast Surprise, имеют приоритет.

Тем не менее, в отношении ответов Даниэля С. Собраля и айообо, мое отношение состоит в том, что, если дизайн класса становится проблемой из-за непредвиденных событий, это работа 30 секунд в среде IDE для приватизации полей и добавления аксессуаров, и не более 5 или 10 минут, чтобы исправить сломанные ссылки, если их не будет сотни. Все, что не получается в результате, получает unit test, оно должно было быть в первую очередь.: -)

[Edit: Эффективная Java довольно решительно против этой идеи, отмечая, что она "менее опасна" для неизменяемых полей.]

Ответ 5

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

  • public final выглядит наиболее чистым для неизменяемых типов.
  • Изменяемые типы могут быть изменены средствами доступа, даже если это не предназначено - в параллельных средах это может привести к большому количеству головной боли.
  • Не может быть конструктора без аргументов. Это важно, если вам нужны заводские методы (например, для LMAX Disruptor). Аналогичным образом создание экземпляров ваших объектов с помощью отражения становится более сложным.
  • Геттеры и сеттеры могут иметь побочные эффекты. Использование public final ясно говорит программисту, что никакой скрытой магии не происходит, и объект по своей сути тупой :)
  • Вы не можете вернуть оболочку или экземпляр производного класса для средства доступа. Опять же, это то, о чем вы должны знать, когда полю присваивается его значение. По моему мнению контейнерные классы не должны беспокоиться о том, что возвращать кому.

Если вы находитесь в стадии разработки, и никакие рекомендации не мешают вам, и проект изолирован, или у вас есть контроль над всеми вовлеченными проектами, я бы предложил использовать public final для неизменяемых типов. Если позже вы решите, что вам нужны геттеры, Eclipse предлагает RefactorEncapsulate Field... который автоматически создает их и корректирует все ссылки на поле.

Ответ 6

Не совсем понятно, будет ли кто-то использовать ваш код через API. Вам также не хватает возможности проверить ввод данных, если вы собираетесь потребовать его позже.