I want a class that I can create instances of with one variable unset (the id
), then initialise this variable later, and have it immutable after initialisation. Effectively, I'd like a final
variable that I can initialise outside of the constructor.
Currently, I'm improvising this with a setter that throws an Exception
as follows:
public class Example {
private long id = 0;
// Constructors and other variables and methods deleted for clarity
public long getId() {
return id;
}
public void setId(long id) throws Exception {
if ( this.id == 0 ) {
this.id = id;
} else {
throw new Exception("Can't change id once set");
}
}
}
Is this a good way of going about what I'm trying to do? I feel like I should be able to set something as immutable after it's initialised, or that there is a pattern I can use to make this more elegant.
I have this class, similar to JDK's
AtomicReference
, and I use it mostly for legacy code:I has single responsibilty and check both
get
andset
calls, so it fails early when client code misuse it.Let me suggest you a little bit more elegant decision. First variant (without throwing an exception):
Second variant (with throwing an exception):
Here are two ways; the first is basically the same as some others mentioned in other answers, but it is here to constrast with the seconds. So the first way, Once is to have a value that can be set only once by enforcing that in the setter. My implementation requires non-null values, but if you want to be able to set to null, then you would need to implement an 'isSet' boolean flag as suggested in other answers.
The second way, Lazy, is to provide a function that lazily supplies the value once the first time the getter is called.
So you might use these as follows;
I think the singleton pattern might be something you should look into. Google around a bit to check if this pattern meets your design goals.
Below is some sudo code on how to make a singleton in Java using enum. I think this is based off Joshua Bloch's design outlined in Effective Java, either way it's a book worth picking up if you don't have it yet.
Usage:
Marking a field private and not exposing a
setter
should be sufficient:if this is insufficient and you want someone to be able to modify it X times you can do this:
This approach is akin to design by contract, wherein you validate the state of the object after a mutator (something that changes the state of the object) is invoked.