When should we use an uninitialized static final variable? I know that an uninitialized static final variable can only be assigned values in the static initializer block, but I can't think of any real use for this.
It's used when initializing the variable can't be done in a single line. For example:
private static final Map<String, String> CACHE;
static {
Map<String, String> cache = new HashMap<String, String>();
cache.put("foo", "bar");
cache.put("zim", "bam");
// lots of other entries
CACHE = Collections.unmodifiableMap(cache);
}
I assume you mean:
public static final Object obj;
with no initial value explicitly assigned?
You can assign it in the static block based on some computation that can only occur at runtime, like reading some property file to create an Application-wide constant that is not known at compile time.
Basically if you need to assign a value which can't be easily represented in a single expression. For example, you might want to perform some logic to build an immutable map, and then assign it.
Generally it's more readable to put the "building" logic into a separate static method, and use that in the normal assignment though:
private static final Map<String, String> FOO_MAP = buildFooMap();
If the initialiser for a static field can throw an exception you cannot initialise it in one line, you have to have a static block or a static method.
Static+Final
In short,
Static - to make it as a class variable - Independent of the Object (Accessible to every object the same location always)
Final - to make it a constant.(If final is before a Variable ofcourse!)
Where do we need only static?
=> May be to count the number of instances an object.
Where do we need only final?
=> Well to make something constant!
Where do we need static+final?
=> Make the variable accessible to every object and to make a constant.As in creating a class for COLOR may be.
For blank static variables the initialization has be done by static block.
public class StaticDemo
{
private static final String name;
static
{
name = "yash";
}
}
and why to use blank one's? since may be you can't initialize at the beginning.I accept the previous one's.
The static final variable must be initialized at the time of creation, unlike blank final variables, you cannot defer initialization to constructor because they are static.
Related
The java documentation mentioned that
The static modifier, in combination with the final modifier, is also
used to define constants.
I was just wondering, can the final keyword alone be used to define a constant in java. I know that variable declared with final keyword and without static keyword can't be changed, but does it count as a constant?
You need the static keyword to eliminate the context of the Class instance.
Take a look at the following code:
public class Main {
public static final String CONST;
static {
if((System.currentTimeMillis() % 2) == 0) {
CONST = "FOO";
}
else {
CONST = "BAR";
}
}
public final String CONST2;
public Main(){
if((System.currentTimeMillis() % 2) == 0) {
CONST2 = "FOO";
}
else {
CONST2 = "BAR";
}
}
}
While creating multiple instances of Main will result in different values for CONST2, CONST will be initialized when the class is loaded and so stays the same over several instances of Main.
The more interesting is that you may even have a static final variable with different values in case that multiple ClassLoaders are involved.
So, a constant in Java is a final static variable that is initialized with a constant value.
Final variables are immutable, but static specifies that it's not an instance variable but class variable. So you can use final variable inside your class but if you need it to be used as a application-wide constant it should be public, and you definitely don't want to create the new class instance to access your constant so it should be static.
In general you may use just final for method constants.
http://java.about.com/od/understandingdatatypes/a/Using-Constants.htm
By not defining static you will create a copy of your constant with each new instance. I am not sure if constant must be unique by definition, but do not think, that you want multiple copies of the same constant.
If you declare a variable as final you can assign a value to it only once.
A non static final variable can only be declared inside a scope, e.g. in a method like that:
public static void main(String[] args) {
final int maxValue = 4711;
// ...
}
Inside this method you cannot change the value of maxValue. So it is a constant but only visible inside the scope of this method.
You can also declare a class attribute as final:
public class MyClass {
final String name;
public MyClass() {
name = "Big Jim";
}
// ...
}
So after assigning a value to the final attribute you cannot change it anymore.
Apparently it is not possible to access these variables from static methods.
So most often we use final together with static for constants, because these are not bound to specific instances.
Beware that the final keyword only protects you from assigning new values to the variable. If the type is a mutable class you can still change the inner state of the instance.
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?
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.
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'm not sure why, but that's the behavior I'm getting. To avoid this in your own example, simply change Test.map to map, and change the name of the other map variable.
P.S. Robby's answer explains the reason for the behavior.
I realized a workaround, using a method to init the field instead of a static block. Inside the method the variable can of course be named whatever the foo it wants to be named:
public static final Map<String,Object> map = initMap();
private static Map<String,Object> initMap() {
...
}
I am having some confusion between static final class variable and final instance variable.
Here is the sample code:-
class Foof{
final int size=3;
final int whuffie;
Foof()
{
whuffie=42;
}
public static void main(String [] args){
Foof obj1 = new Foof();
Foof obj2 = new Foof();
obj1.size=53; //compile time error
System.out.println(obj1.size);
obj2.whuffie=45; //compile time error
System.out.println(obj2.whuffie);
}
}
Error:-
ankit#stream:/home/Data/JAVA/practice/src/test.com/test-20121031_static_demystified$ javac Foof.java
Foof.java:14: error: cannot assign a value to final variable size
obj1.size=53; //compile time error
^
Foof.java:16: error: cannot assign a value to final variable whuffie
obj2.whuffie=45;
^
2 errors
So my question is, what is the point of having final instance variables if they can't have a different values per different instance. I mean if they have same value for each instance then why don't we declare them as class variable(static final class variable) as this would serve the same purpose and the we don't need to create objects in order to access them.
EDIT -1:-
class Foof{
final int size=3;
final int whuffie;
Foof()
{
whuffie=42;
size = 23; //compile-time error.
}
public static void main(String [] args){
Foof obj1 = new Foof();
Foof obj2 = new Foof();
//obj1.size=53;
System.out.println(obj1.size);
//obj2.whuffie=45;
System.out.println(obj2.whuffie);
}
}
Error:-
Foof.java:8: cannot assign a value to final variable size
size = 23;
^
1 error
According to the error, i can make out that first size is assigned a value =3 during object creation.
So my question is, what is the point of having final instance variables if they can't have a different values per different instance.
They can, but those values can't be changed after creation. You can only assign values to final instance fields within instance variable initializers and constructors, and you must assign values to all instance fields that way.
Note that in your code here:
Foof()
{
whuffie=42; //compile time error
}
... the comment is incorrect. That assignment should be perfectly valid.
Final fields are useful for implementing immutability - which helps make it easy to reason about an object. For example, String is immutable, so if you validate a string and then keep a copy of the reference, you know that validation will still be correct later on.
Compare that with java.util.Date, where if you really want to have any faith in validation being useful, you need to create a defensive copy of the Date value and not provide the reference to any other code, in case it changes the underlying instant being represented.
A final is final as soon as you asign a value to it. You can't change it later.
You can't modify a final variable after initializing on declaration or in the constructor(s).
Using the static keyword doesn't make it modifiable. It just means the final variable can be accessed through the class name or instance variable, the variable is still immutable.
Actually static and non static final variable are needs when we are creating any varible as a class specific then will declare it as static and if object level then will declare it as non static variable.
For example,
We have a country as a class and and will have two data members of that class like
timezone and gravity.
we declred both of them as final, but timezone is object specific(timezone of every country is different but same throughout the country) and gravity is class specific(gravity of each country is same as earths gravity) so we are declared gravity as static final.
final variables are typically used to define things that should never change. You can write to it one time and then it is set forever.
You might use this in a constructor to set an ID for an object or something similar.
For final variables you can assign value only once.
It is generally used in case where you don't want the values of variables to be changed later in your program.
Static variables only one instance is created per class, irrespective of number of objects of that class you create.
what i basicly want is this:
public class Test
{
private static final Integer a;
public Test(Integer a)
{
this.a = a;
}
}
This obviously doesn't work, cause the 2nd created instance would try to override the final variable.
So is there a way to give all the instances the same immutable value via the constructor?
Static final values should be initialized in a static context, not by instances.
One options is to set the value in the declaration:
private static final Integer a=FileConfig.getInstance().getA();
Each class can have a static {} block where code is called to initialize the static parts of the class.
static {
a = FileConfig.getInstance().getA();
}
Finally, you can set the value from a static method
private static int getA() {
return FileConfig.getInstance().getA();
}
private static final Integer a=getA();
In closure, static instance initialization does not belong in instance constructors.
If the configuration values change sometimes, there is simply no reason to store the value a in a static final variable. If you want to create each instance with the constant a in the constructor, what is the purpose of a static field in the first place? Somehow, when you call the constructor for the first time, you are passing in a value from somewhere. If the value deserves to be static and final, you can acquire it from within the static initializer. If the configuration is not a singleton, but every instance always produces the same value of a, you could easily do a = new FileConfig().getA();.
Other than that, you could make the value non-final, and rest assured that since you always put in the same value of a, the static variable will not change.
Still, you could make a a final instance variable of the class, set in the constructor.
So is there a way to give all the instances the same immutable value via the constructor?
I assume you want a value to be assigned to a the first time an object of type Test is created but not when any subsequent instance is created. In that case you cannot declare it final. a will be null initially, the constructor has to check if it is null and assign it a value in that case.
But I urge you to look at the design, especially why the caller have to provide the value. Isn't it counter-intuitive that after the second Test object is created Test.a does not change in the following case?
// assume this is the first `Test` object created:
Test t = new Test(5); // Test.a is 5
Test t = new Test(6); // Test.a is *still* 5
I have an interesting question on initialization. I have the following code:
public class ErrorLookupProvider {
private static final ErrorLookupProvider INSTANCE = new ErrorLookupProvider();
private static Map<Long, List<String>> map = new HashMap<Long, List<String>>();
private ErrorLookupProvider() {
init();
}
private void init() {
map.put(123L, ImmutableList.of("abc", "def"));
}
public static ErrorLookupProvider getInstance() {
return INSTANCE;
}
}
Now when I call ErrorLookupProvider.getInstance(), I hit an NPE. The map inside init() is not initialized with the new HashMap.
If I change the declaration of map to be final, then I see that it is initialized. Or, even if I remove static and make it a private class variable as private Map<.....> that works too.
I haven't been able to figure out why this happens. Can someone explain what is happening here?
Switch the order of the map and singleton instance initializations.
Static initialization occurs in the order it's encountered in the source.
See JLS 12.4.2 Detailed Initialization Procedure, steps 6 (the final part) and 9 (the "order" part).
(The singleton implementation and mucking with statics in a ctor, separate issue.)
quoting from http://javapapers.com/core-java/explain-the-final-keyword-in-java/
A variable that is declared as final and not initialized is called a blank final variable. A blank final variable forces the constructors to initialise it.
That is why when declared final it is initialised
ADDED: Order matters. Put the declaration for your static map before the declaration of INSTANCE. The Java compiler is a bit stupid about ordering...
Since map is static, it is shared among all instances of ErrorLookupProvider. Therefore, it is probably a mistake to play with it in the constructor. If you create multiple ErrorLookupProviders, you will redundantly add to the map many times. Instead, initilize it in a static initializer block. Or, if it is really meant to be independent between instances of ErrorLookupProvider, don't make it static.