Salman A. Kagzi
Salman A. Kagzi

Reputation: 4053

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?

Upvotes: 5

Views: 4407

Answers (4)

Etienne
Etienne

Reputation: 31

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.

Upvotes: 3

StKiller
StKiller

Reputation: 7941

Why do you need to set the value of final variable from a private method ? You may do it in this way :

public class FinalTest {
   private final Object a;
   {
      a=new Object();
   }

   //Constructor
   public FinalTest() {
   }
}

In this case the object will be initialized on every FinalTest initialization.

Upvotes: 1

Andrew White
Andrew White

Reputation: 53496

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
  }
}

Upvotes: 10

Ha.
Ha.

Reputation: 3454

Final checking is done at compile time not at runtime time. In your case compiler can't be sure that setA would not be called from some other method.

Upvotes: 1

Related Questions