2

In Java, we can initialize a final field in constructors both in the base class and its subclasses, and also in an inline initializer block in the base class. However, it seems that we can not initialize final fields in an inline initializer block in a subclass. This behavior mainly affects anonymous classes from which super constructors can not be called.

abstract class MyTest {

    final protected int field;

    public MyTest() {
        // default value
        field = 0;
    }

}

MyTest anonymTest = new MyTest() {
    {
        // Error: The final field MyTest.field cannot be assigned
        field = 3;
    }
};

Is there any way to initialize an inherited final field in an anonymus class?

Comment: This question is not about constructors, but about final field initialization.

Dávid Horváth
  • 4,050
  • 1
  • 20
  • 34
  • This is not about constructors, but about final field initialization. – Dávid Horváth Apr 04 '16 at 19:24
  • True, but the *only* situation in which you're able to set a `final` field from a subclass is through a super constructor. So that duplicate covers the only valid situation for your question. – resueman Apr 04 '16 at 19:25
  • I do not agree. If there is no other way than the constructor, then this is the answer to the question. – Dávid Horváth Apr 04 '16 at 19:30
  • *"If there is no other way than the constructor, then this is the answer to the question."* ... my question would be: why do you want to be able to construct instances using a mechanism other than that one which was intended, i.e. constructors? The constructor is supposed to be that one place where objects are both initialized and validated. Circumventing this mechanism seems unwise. – scottb Apr 04 '16 at 19:38
  • @scottb: In fact, there are several reasons. For example `new Foo(){{a=1;b=2;}}` is more explicit/understandable than `new Foo(1,2){}`. Actually the original problem is that abstract classes do not allow uninitialized `final` fields. See: http://stackoverflow.com/questions/2327509/abstract-class-with-final-uninitialized-field/2327534?noredirect=1#comment60425594_2327534 – Dávid Horváth Apr 04 '16 at 19:57
  • @DávidHorváth: I don't think you'll ever get me to agree that `new Foo() {{a=1; b=2;}}` is more readable or understandable than `new Foo(1,2);`. For more complex cases involving initialization of immutable classes, Builders are also very easy to read and understand, and they facilitate the use of optional parameters. – scottb Apr 04 '16 at 22:03
  • Generally, I agree. Constructor call is the standard and safe way to initialize fields, and Builder is a great solution for complex situations. However, in some simple cases, it whould be useful, simple and elegant, if we could explicitly set the fields, regardless of they are final or not. This is not as C-ish as it seems at first look. – Dávid Horváth Apr 05 '16 at 00:25

2 Answers2

5

You have to initialize final instance variables either during declaration or in the constructor. However, you can provide the value to the constructor

abstract class MyTest {

    final protected int field;

    public MyTest() {
        // default value
        this(0);
    }

    public MyTest(int f) {
        field = f;
    }

}


MyTest anonymTest = new MyTest(3) {
};

Update: Added constructor for using default value

gustf
  • 1,959
  • 13
  • 20
1

Final instance variables must be initialized in a constructor.

abstract class MyTest {

final protected int field;

public MyTest() {
    // default value
    field = 0;
}

public MyTest(int val)
{
   // will set the final field to the specified val
   field = val;
}

}
KevinO
  • 4,303
  • 4
  • 27
  • 36