I see most immutable POJOs written like this:
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;
}
}
Yet I tend to write them like this:
public class MyObject {
public final String foo;
public final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
}
Note the references are final, so the Object is still immutable. It lets me write less code and allows shorter (by 5 chars: the get
and ()
) access.
The only disadvantage I can see is if you want to change the implementation of getFoo()
down the road to do something crazy, you can't. But realistically, this never happens because the Object is immutable; you can verify during instantiation, create immutable defensive copies during instantiation (see Guava's ImmutableList
for example), and get the foo
or bar
objects ready for the get
call.
Are there any disadvantages I'm missing?
EDIT
I suppose another disadvantage I'm missing is serialization libraries using reflection over methods starting with get
or is
, but that's a pretty terrible practice...
final
doesn't make a variable the object immutable. I normally use a design where I definefinal
fields before creating callback so that callback can access those fields. It can, of course call all methods including anysetX
methods.String
,int
, orMyObject
. In the first version,final
is only to ensure that methods other than the constructor within the class don't try tobar = 7;
, for example. In the second version,final
is necessary to prevent consumers from doing:MyObject x = new MyObject("hi", 5); x.bar = 7;
.Object
is still immutable." is misleading - that way it appears you think anyfinal Object
is immutable, which it isn't. Sorry for the misunderstanding.myObj.getFoo().setFrob(...)
.