Widzę najbardziej niezmienne POJO napisane w ten sposób:
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;
}
}
Mimo to mam tendencję do pisania ich w ten sposób:
public class MyObject {
public final String foo;
public final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
}
Zauważ, że odniesienia są ostateczne, więc Obiekt jest nadal niezmienny. Pozwala mi pisać mniej kodu i umożliwia krótszy (o 5 znaków: dostęp get
i ()
).
Jedyną wadą, jaką widzę, jest to, że jeśli chcesz zmienić implementację w getFoo()
dół drogi, aby zrobić coś szalonego, nie możesz. Ale realistycznie to się nie zdarza, ponieważ Obiekt jest niezmienny; możesz zweryfikować podczas tworzenia instancji, tworzyć niezmienne kopie obronne podczas tworzenia instancji (patrz ImmutableList
na przykład Guava ) i przygotować obiekty foo
lub bar
obiekty na get
wezwanie.
Czy brakuje mi wad?
EDYTOWAĆ
Przypuszczam, że kolejną wadą, której mi brakuje, są biblioteki serializacji wykorzystujące refleksję nad metodami zaczynającymi się od get
lub is
, ale to dość okropna praktyka ...
źródło
final
nie czyni zmiennej niezmienną. Zwykle używam projektu, w którym definiujęfinal
pola przed utworzeniem wywołania zwrotnego, aby wywołanie zwrotne mogło uzyskać dostęp do tych pól. Może oczywiście wywoływać wszystkie metody, w tym dowolnesetX
.String
,int
lubMyObject
. W pierwszej wersjifinal
ma jedynie zapewnić, że metody inne niż konstruktor w klasie nie będą próbowaćbar = 7;
na przykład. W drugiej wersji,final
jest konieczne, aby zapobiec konsumentów robi:MyObject x = new MyObject("hi", 5); x.bar = 7;
.Object
nadal są niezmienne. ” Są mylące - w ten sposób wydaje się, że uważasz, że każdyfinal Object
jest niezmienny, a tak nie jest. Przepraszam za nieporozumienie.myObj.getFoo().setFrob(...)
.Odpowiedzi:
Cztery wady, o których mogę myśleć:
To powiedziawszy, twoja wersja jest zdecydowanie bardziej zwięzła. Gdyby to była klasa specjalistyczna, która jest używana tylko w ramach określonego pakietu (być może zakres pakietu jest tutaj dobrym pomysłem), to mogę rozważyć to jednorazowo. Ale nie ujawniłbym takich głównych API.
źródło
Pozbądź się również pobierających / ustawiających i wszystko w porządku!
Jest to bardzo kontrowersyjny temat wśród programistów Java.
W każdym razie istnieją dwie sytuacje, w których używam zmiennych publicznych zamiast (!) Getters / setters:
źródło
Słowami laika:
źródło
Jedną z możliwych wad, którą widzę od razu, jest to, że jesteś przywiązany do wewnętrznej reprezentacji danych w klasie. To chyba nie jest wielka sprawa, ale jeśli użyjesz seterów i zdecydujesz, że foo i bar zostaną zwrócone z innej klasy zdefiniowanej gdzie indziej, klasy zużywające MyObject nie będą musiały się zmieniać. Wystarczy dotknąć MyObject. Jeśli jednak użyjesz nagich wartości, musisz dotknąć wszędzie tego, z którego korzystałem MyObject.
źródło