Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting a final class attribute

Is it possible to set a value for a final attribute from a Private method called from the Constructor of that Object?

public class FinalTest {
  private final Object a;
  //Constructor
  public FinalTest() {
    setA();
  }

  private void setA() {
    a = new Object;
  }
}

For the above class, compiler gives me an error saying I can't set the value for 'a' from the method.

I understand that its not possible to set value for a final variable from outside a constructor, but in the above case, I am actually doing it in a way within the constructor. So why isn't this allowed?

like image 484
Salman A. Kagzi Avatar asked Dec 09 '22 09:12

Salman A. Kagzi


2 Answers

It's not allowed because you could call setA() via some other non-constructor method later on which would violate the final protection. Since final is a compile time enforced operation, the compiler enforces final by forcing initialization to occur in constructors or in-line.

In your simple example, all looks good but if you later updated your class to something like the following, the problem become more obvious...

public class FinalTest {
  private final Object a;
  //Constructor
  public FinalTest() {
    setA();
  }

  private void setA() {
    a = new Object;
  }

  public void doSomething() {
   this.setA(); // not good because a is final
  }
}
like image 101
Andrew White Avatar answered Dec 11 '22 22:12

Andrew White


Just a note: The compiler has to assume the worst case scenario. By declaring an attribute "final", the compiler has to ensure that the attribute cannot be modified outside of the constructor.

In a case where the method is called using reflection (for example), the compiler would never see it, ever. It's a lot easier to prove something is possible than impossible, that is why the compiler works the way it does.

like image 36
Etienne Avatar answered Dec 11 '22 22:12

Etienne