jamesdeath123
jamesdeath123

Reputation: 4606

How to allow variables being set only once in java

I need to implement a class in java where its field needs to be set only once, but it's value is not known at field declaration. To do so I have:

public class MyClass {
    private String field1 = null;
    public void setField1(String value) {
        if (field1 == null) {
            field1 = value;
        }
     }
}

However what I have do not prevent users to call setField1 more than once. That may lead to confusion where a user is trying to set it (without knowing it has been set somewhere else) and then the user will get confused by the field1 is not giving the value they set - until they go into the setField1 method to see what happened.

The other solution that I don't like is make a constructor to take into the value of field1, and then provide no setter. Because it makes the class a lot harder to be extended, when multiple String fields are needed - in this approach, the constructor will need to take in a couple String as parameters, and then the user can be so easily confused by/missing the parameters.

And apparently setting field1 as final won't work either.

What should I do to prevent the issue I mentioned above?

Upvotes: 2

Views: 3201

Answers (2)

Matt Timmermans
Matt Timmermans

Reputation: 59174

You should generally use the builder pattern for cases like this: https://en.wikipedia.org/wiki/Builder_pattern

MyClass instance = (new MyClassBuilder())
    .setField1(...)
    .setField2(...)
    .build();

Your builder object lets you set all the fields and options you like, but the MyClass instance that it builds does not.

Upvotes: 4

Tagir Valeev
Tagir Valeev

Reputation: 100209

The common practice in such case is to throw a RuntimeException. In your case IllegalStateException suits best:

public void setField1(String value) {
    if (field1 != null) {
        throw new IllegalStateException("setField1 was already called");
    }
    field1 = Objects.requireNonNull(value);
}

Also note that it's better to check the passed string for null (I added Objects.requireNonNull for this).

You cannot control this at compile time, because it's impossible to analyze program to say exactly whether the method called once or more without actually running the program.

Upvotes: 6

Related Questions