Я вижу большинство неизменных POJO, написанных так:
public class MyObject {
private final String foo;
private final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
public String getFoo() {
return foo;
}
public int getBar() {
return bar;
}
}
Тем не менее, я склонен писать их так:
public class MyObject {
public final String foo;
public final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
}
Обратите внимание, что ссылки являются окончательными, поэтому объект по-прежнему неизменен. Это позволяет мне писать меньше кода и обеспечивает более короткий (на 5 символов: get
и ()
) доступ.
Единственный недостаток, который я вижу, - если вы хотите изменить реализацию getFoo()
в будущем, чтобы сделать что-то сумасшедшее, вы не можете. Но на самом деле этого никогда не происходит, потому что Объект неизменен; Вы можете проверить во время создания экземпляра, создать неизменные защитные копии во время создания экземпляра (см., ImmutableList
например, Guava ) и получить объекты foo
или, bar
готовые к get
вызову.
Есть ли недостатки, которые я пропускаю?
РЕДАКТИРОВАТЬ
Полагаю, еще один недостаток, который мне не хватает, - это библиотеки сериализации, использующие рефлексию над методами, начинающимися с get
или is
, но это довольно ужасная практика ...
источник
final
не делает переменную неизменным объектом. Обычно я использую дизайн, в котором я определяюfinal
поля перед созданием обратного вызова, чтобы обратный вызов мог получить доступ к этим полям. Конечно, он может вызывать все методы, включая любыеsetX
методы.String
,int
илиMyObject
. В первой версииfinal
только для того, чтобы гарантировать, что другие методы, кроме конструктора внутри класса, не пытаютсяbar = 7;
, например. Во втором варианте,final
необходимо , чтобы предотвратить потребителей делать:MyObject x = new MyObject("hi", 5); x.bar = 7;
.Object
все еще неизменны». Вводит в заблуждение - таким образом, кажется, вы думаете, что что-тоfinal Object
неизменно, а это не так. Извините за недопонимание.myObj.getFoo().setFrob(...)
.Ответы:
Четыре недостатка, о которых я могу подумать:
Тем не менее, ваша версия определенно более краткая. Если бы это был специализированный класс, который используется только в определенном пакете (может быть, здесь полезна область действия пакета), то я мог бы рассмотреть это для разовых предложений. Но я бы не стал раскрывать такие основные API.
источник
Избавьтесь от добытчиков / сеттеров тоже, и вы в порядке!
Это очень спорная тема среди Java-программистов.
В любом случае, есть две ситуации, где я использую публичные переменные вместо (!) Методов получения / установки:
источник
По словам непрофессионала:
источник
Один возможный недостаток, который я могу видеть, заключается в том, что вы привязаны к внутреннему представлению данных в классе. Это, вероятно, не так уж и сложно, но если вы используете сеттеры и решаете, что foo и bar будут возвращены из какого-то другого класса, определенного где-то еще, то для классов, потребляющих MyObject, не потребуется изменять. Вам нужно будет только коснуться MyObject. Тем не менее, если вы используете открытые значения, то вам придется касаться везде, где я использовал MyObject.
источник