Assign a static leaf field with the same name

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

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

I am trying to do the same in a static context using qualification access with a 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 does not want to have anything to do with this code. I have several variables like this, and for all of them, he continues to shout: "it is impossible to assign a value to a final variable." If I do not assign it, he will instead complain about a "variable not initialized." If I assign a static field at the beginning and try to make the map immutable afterwards, she complains that "the variable may have already been assigned." It does not suit anything.

Is this a flaw in the language or a bug in the compiler? What is the best way to crush the compiler at runtime?

+5
source share
3 answers

The easiest way to solve the following:

 import java.util.*; class Test { public static final Map<String,Object> map; static { Map<String,Object> contents = new HashMap<>(); map = Collections.unmodifiableMap(contents); } } 

It seems somehow that if you qualify a constant with a class name in Java 8, the compiler will not get it.

Update

After some additional digging, it seems that the Java Language Specification explicitly states that to assign it is necessary to use a simple (unqualified) name of the final fields (highlighting mine):

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

Similarly, each empty final variable must be assigned no more than once; he must be definitely unassigned when assignment to him occurs.

Such an assignment is defined as if and only if the simple name of the variable (or, for the field, the simple name qualifies this) occurs on the left side of the job statement .

+5
source

It looks like it works to say

 public static final <something> x; static { x = <whatever>; } 

but not

 public static final <something> x; static { MyClass.x = <whatever>; } 

I am not sure why, but this is the behavior that I get. To avoid this in your own example, just change Test.map to map and change the name of another map variable.

PS Robbie's answer explains the reason for the behavior.

+1
source

I figured out a workaround using a method to initialize a field instead of a static block. Inside a method, a variable, of course, can be named as it will be called foo:

 public static final Map<String,Object> map = initMap(); private static Map<String,Object> initMap() { ... } 
0
source

Source: https://habr.com/ru/post/1206313/


All Articles