Search code examples
javaclass-designfinal

How do I set a final field via a setter?


I have the following abbreviated class:

public class Employee {

    private final float pointPosition;

    public Employee(float pointPosition) {
        this.pointPosition = pointPosition;
    }

}

I'd like to do checks on the pointPosition being passed in by the constuctor, to ensure that it doesn't exceed 1.0.

I tried moving the assignment to it's own private setter method that does a precondition check, but obviously that gave me an error since I'm reassigning a final field outside of the constructor.

I could change the constructor to something like:

public Employee(float newPointPosition) {
    verifyPointPosition(newPointPosition); //Will throw
    this.pointPosition = pointPosition;
}

But I'd prefer to have it all wrapped up neatly in it's own method.

What are my options here?


Solution

  • Option 1: Don't make it final

    You could just not make it final and make the setter private.


    Option 2: Do the check and set in the Constructor

    That's what you already showed.


    Option 3: The hackish way

    You can set final variables with reflection, however i would definitely not recommend this unless you're forced to.


    I'd go with Option 2. If you're worried that your constructor gets too messy, you can just create additional constructors and set them private, for example:

    public class MyClass {
        private final float variable;
    
        public MyClass(float variable) {
            this();
            if(variable < 0.0f || 1.0f < variable)
                throw new IllegalArgumentException("'variable' has to be between 0.0 and 1.0");
            this.variable = variable;
        }
    
        private MyClass() {
            //Set everything else
        }
    }
    

    Actually, this Code will not compile.