views:

4671

answers:

8

Is there a solution to use a final variable in a Java constructor? The problem, if I init. a final var. like:

private final String name = "a name";

then I cannot use it in the constructor, while java first runs the constructor an then the fields... Is there a solution to get in contact with the final var. in the constructor?

+4  A: 

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";
Hank Gay
+2  A: 

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

Outlaw Programmer
a way without a static field?
Tobiask
@Tobiask: Why don't you want a static field?
sfossen
It's immutable, so you might as well make it static.
Adam Jaskiewicz
no, in a multiuser environment static var. aren´t the best way...
Tobiask
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.
Adam Jaskiewicz
+1  A: 

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

Adam Jaskiewicz
+12  A: 

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
Johannes Weiß
+1  A: 
private static final String name = getName();

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

daanish.rumani
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.
DJClayworth
+2  A: 

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;
}
sfossen
A: 

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.

soulmerge
Technically it is the constructor that is (implicitly) executing the field initialisation logic.
Tom Hawtin - tackline
Well, ok. The fields get evaluated first nonetheless.
soulmerge
+1  A: 

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();
        }
}
Joachim Sauer