Я бачу більшість непорушних 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
) та підготуйте foo
або bar
об'єкти готові до get
виклику.
Чи є якісь недоліки, яких мені не вистачає?
EDIT
Думаю, ще один недолік, якого мені не вистачає, - це бібліотеки серіалізації, що використовують роздуми над методами, починаючи з get
або is
, але це досить жахлива практика ...
String
, int
або MyObject
. У першій версії final
потрібно лише забезпечити, наприклад, інші методи, ніж конструктор у класі, не намагаються bar = 7;
, наприклад. У другому варіанті, final
необхідно , щоб запобігти споживачів робити: MyObject x = new MyObject("hi", 5); x.bar = 7;
.
Object
все ще незмінне. " Вводить в оману - таким чином, здається, ви вважаєте, що будь- final Object
яке незмінне, а це не так. Вибачте за непорозуміння.
myObj.getFoo().setFrob(...)
.
final
не робить змінну об'єкта незмінним. Я зазвичай використовую дизайн, де я визначаюfinal
поля перед створенням зворотного дзвінка, щоб зворотний виклик міг отримати доступ до цих полів. Звичайно, можна викликати всі методи, включаючи будь-якіsetX
методи.