Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assign to static final field of same name

Tags:

java

To distinguish between an instance field and a local variable of the same name we can qualify access to the field with the prefix this.:

class Test {
    public final Foo x;

    public Test(Foo x) {
        this.x = x;
    }
}

I'm trying to do the same thing in a static context by qualifying access with the class name:

import java.util.*;

class Test {
    public static final Map<String,Object> map;

    static {
        Map<String,Object> map = new HashMap<>();

        // ... 
        // assume I fill the map with useful data here
        // ...

        // now I want to freeze it and assign it to the field
        Test.map = Collections.unmodifiableMap(map);
    }
}

The compiler wants nothing to do with this code. I have several variables like this and for all of them it keeps yelling: "cannot assign a value to final variable". If I don't assign to it, it complains "variable not initialized" instead. If I assign to the static field at the beginning and try to make the map unmodifiable afterwards, it complains "variable might already have been assigned". It's not happy with anything.

Is this a flaw in the language, or a bug in the compiler? What's the best way to squash the compiler into doing as its told?

like image 786
Boann Avatar asked Nov 06 '14 02:11

Boann


People also ask

How do you assign a value to the final static variable in Java?

In Java, non-static final variables can be assigned a value either in constructor or with the declaration. But, static final variables cannot be assigned value in constructor; they must be assigned a value with their declaration.

Can static fields be final?

Constant variables never change from their initial value. Static variables are stored in the static memory, mostly declared as final and used as either public or private constants.

Can final member variables be made static?

We can initialize a final static variable at the time of declaration. Initialize inside a static block : We can also initialize a final static variable inside a static block because we should initialize a final static variable before class and we know that static block is executed before main() method.

How do you initialize a static final variable?

The only way to initialize static final variables other than the declaration statement is Static block. A static block is a block of code with a static keyword. In general, these are used to initialize the static members. JVM executes static blocks before the main method at the time of class loading.


1 Answers

The easiest way to solve is as follows:

import java.util.*;

class Test {
    public static final Map<String,Object> map;

    static {
        Map<String,Object> contents = new HashMap<>();

        map = Collections.unmodifiableMap(contents);
    }
}

Somehow it seems that if you qualify the constant with the class name in Java 8, the compiler won't have it.

Update

After some more digging, it seems that the Java Language Specification explicitly states that the simple (unqualified) name needs to be used for the assignment of final fields (highlighting mine):

For every access of a local variable or blank final field x, x must be definitely assigned before the access, or a compile-time error occurs.

Similarly, every blank final variable must be assigned at most once; it must be definitely unassigned when an assignment to it occurs.

Such an assignment is defined to occur if and only if either the simple name of the variable (or, for a field, its simple name qualified by this) occurs on the left hand side of an assignment operator.

like image 58
Robby Cornelissen Avatar answered Oct 20 '22 15:10

Robby Cornelissen