8

Is there a solution to use a final variable in a Java constructor? The problem is that if I initialize a final field like:

private final String name = "a name";

then I cannot use it in the constructor. Java first runs the constructor and then the fields. Is there a solution that allows me to access the final field in the constructor?

6
  • 1
    I assume that you want to change the value on the constructor right ? Commented Mar 24, 2009 at 14:25
  • 2
    I'm voting to close because, from my understanding, it turns out this is not really a problem at all. What the OP is trying to do should work. Commented Mar 24, 2009 at 15:02
  • 1
    The constructor implicitly executes the field initialisation immediately before calling the super constructor. Commented Mar 24, 2009 at 15:05
  • 5
    @Tom, actually, all field initialization occurs after the superclass constructor call. Try looking at the bytecode and see. Under the JVM specification, it is permissible to initialize the fields before the ctor call, but Javac never does so. Commented Sep 10, 2012 at 21:25
  • @Antimony Oops, yes. Actually the outer this of an inner class is available during the call to super (-target 1.4 or later). Commented Sep 11, 2012 at 0:52

9 Answers 9

17

I do not really understand your question. That

public class Test3 {
    private final String test = "test123";

    public Test3() {
        System.out.println("Test = "+test);
    }

    public static void main(String[] args) {
        Test3 t = new Test3();
    }
}

executes as follows:

$ javac Test3.java && java Test3
Test = test123
Sign up to request clarification or add additional context in comments.

Comments

16

Do the initialization in the constructor, e.g.,

private final String name;
private YourObj() {
    name = "a name";
}

Of course, if you actually know the value at variable declaration time, it makes more sense to make it a constant, e.g.,

private static final String NAME = "a name";

Comments

6

We're getting away from the question.

Yes, you can use a private final variable. For example:

public class Account {
    private final String accountNumber;
    private final String routingNumber;

    public Account(String accountNumber, String routingNumber) {
        this.accountNumber = accountNumber;
        this.routingNumber = routingNumber;
    }
}

What this means is that the Account class has a dependency on the two Strings, account and routing numbers. The values of these class attributes MUST be set when the Account class is constructed, and these number cannot be changed without creating a new class.

The 'final' modifier here makes the attributes immutable.

2 Comments

Basically, you get one shot at setting the values in the constructor. After the constructor completes, the attributes are constant.
I get an error "cannot assign a value to final variable value".
3

Marking it static, will allow you to use it in the constructor, but since you made it final, it can not be changed.

private static final String name = "a_name";

is is possible to use a static init block as well.

private static final String name;

static { name = "a_name"; }

If you are trying to modify the value in the constructor, then you can't assign a default value or you have to make it not final.

private String name = "a_name";
Foo( String name )
{
    this.name = name;
}

or

private final String name;

Foo( String name )
{
    if( s == null )
       this.name = "a_name";
    else
       this.name = name;
}

Comments

2

In this case, you can mark the field as 'static' also.

4 Comments

a way without a static field?
@Tobiask: Why don't you want a static field?
It's immutable, so you might as well make it static.
It's immutable. There's no shared mutable state, thus no concurrency issues. You'd be right if it didn't have that final on it.
2

Another possiblity is to initialize the field in an instance initializer blocK:

public class Foo {
        final String bar;

        {
                System.out.println("initializing bar");
                bar = "created at " + System.currentTimeMillis();
        }

        public Foo() {
                System.out.println("in constructor. bar=" + bar);

        }

        public static void main(String[] args) {
                new Foo();
        }
}

Comments

1

In that case, you might as well make it static, too. And Java convention is to name such constants in ALL_CAPS.

Comments

1
private static final String name = getName();

where getName() is a static function that gets you the name.

1 Comment

Beware of this construct if getName() does anything other than return a constant. You can find the logic used by getName() may not have been initialized.
0

I cannot use it in the constructor, while java first runs the constructor an then the fields...

This is not correct, fields are evaluated first, otherwise you couldn't access any default values of members in your constructors, since they would not be initialized. This does work:

public class A {
    protected int member = 1;
    public A() {
        System.out.println(member);
    }
}

The keyword final merely marks the member constant, it is treated as any other member otherwise.

EDIT: Are you trying to set the value in the constructor? That wouldn't work, since the member is immutable if defined as final.

2 Comments

Technically it is the constructor that is (implicitly) executing the field initialisation logic.
Well, ok. The fields get evaluated first nonetheless.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.