Неизменяемый тип: публичные конечные поля против геттера
Мне нужен небольшой контейнер-класс для хранения некоторых строк, которые должны быть неизменными. Поскольку сама строка является неизменным типом, я подумал о чем-то подобном:
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 в этом случае будет просто шаблоном, потому что сама строка является неизменной.
Другие мысли, которые я могу пропустить на этом?
Ответы
Ответ 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 предлагает Refactor
→ Encapsulate Field...
который автоматически создает их и корректирует все ссылки на поле.
Ответ 6
Не совсем понятно, будет ли кто-то использовать ваш код через API.
Вам также не хватает возможности проверить ввод данных, если вы собираетесь потребовать его позже.