Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static final int v/s static int

Tags:

This problem was taken from my Java test study guide. Could some explain why this is the way that it is?

This code prints out the number 5 and not 12. Could you explain why? Could you explain why it would print out 12 if the second variable was also final, and 0 if neither of them were final?

public class Question26 {     public static void main(String[] args) {         System.out.println(Q26.q26.ans);     } }  class Q26 {     public static Q26 q26 = new Q26();     public int ans;     private static final int var1 = 5;     private static int var2 = 7;      public Q26() {         ans = var1 + var2;     } } 
like image 917
user2837858 Avatar asked Mar 16 '14 04:03

user2837858


People also ask

What is difference between static and static final?

The static keyword means the value is the same for every instance of the class. The final keyword means once the variable is assigned a value it can never be changed.

What is final static int?

static means that instead of each instance of the class having that variable, the variable belongs to the class as a whole. final means that the values are constant and cannot be changed. Basically what this means is that it's an integer that is constant for all instances of a certain class at all times.

What is the difference between general static variable and final static variable?

In Java, a static variable is one that belongs to class rather than the object of a class, different instances of the same class will contain the same static variable value. A final variable is one that once after initialized ,after the instantiation of a class (creation of an object) cannot be altered in the program.

What is difference between static final and final static in Java?

They are the same. The order of modifiers is not significant. And note that the same rule applies in all contexts where modifiers are used in Java.


2 Answers

One thing to know where you declare static fields is that those are initialized in order; you cannot write:

public class DoesNotCompile {     private static final int foo = 1 + bar; // ERROR: bar is not defined     private static final int bar = 1; 

In your situation, however, things are a little different:

class Q26 {     // Declared first, but NOT first to be initialized...     public static Q26 q26 = new Q26();     public int ans;     // The honor befalls to this one, since it is declared `final`     private static final int var1 = 5;     private static int var2 = 7; // zero until initialized      public Q26() {         ans = var1 + var2;     } } 

The default value of a non initialized int is 0; since your Q26 instance is declared before var1 and var2, but since var1 is initialized first (since it is final), the result is what you see: ans is 5.

An equivalent to this code could be:

class Q26 {     public static Q26 q26;     private static final int var1;     private static int var2;      static {         var1 = 5;         q26 = new Q26();         var2 = 7;     }      public int ans;      public Q26() {         ans = var1 + var2;     } } 

Further note: there are also static initialization blocks; and order matters for these as well. You cannot do:

public class DoesNotCompileEither {     static {         foo = 3; // ERROR: what is foo?     }     private static final int foo; 

If you put the static initializer below the declaration of foo, then this will compile:

public class ThisOneCompiles {     private static final int foo; // declared     static {         foo = 3; // initialized     } 
like image 84
fge Avatar answered Sep 30 '22 23:09

fge


The static members on your class don't all magically initialize at the same time. Under the hood, Java has to set them - and it's doing it in the order you declared them, with exception of the final one.

Lets re-write that so the issue becomes clearer:

public class Question26 {     public static void main(String[] args) {         System.out.println(Q26.q26.ans);     } } class Q26 {     public static Q26 q26;     public int ans;     private static final int var1 = 5;     private static int var2;      static {         q26 = new Q26();         var2 = 7;     }      public Q26() {         ans = var1 + var2;     } } 

Here the declaration of non-final static members and their initialization have been separated. Putting the initialization in a static block makes it a little more evident that the initialization of those members is code like any other and has an order of execution.

But why is the final variable initialized before q26? Looking at this answer and at the Java specification, it seems that var1 might be getting treated as a compile-time constant expression. Even if it isn't being treated as such though, so long as it is declared and is initialized in one statement, var1 should be initialized by the runtime before the non-final variables:

At run time, static fields that are final and that are initialized with constant expressions are initialized first. This also applies to such fields in interfaces. These fields are "constants" that will never be observed to have their default initial values, even by devious programs.

Citation: http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.2.1

So what if we get crazy, separating the declaration and initialization of the static final member var1? In that case we could actually make your program compile and execute, only to output 0 - which contradicts some of the assertions you made in your question.

public class Question26 {     public static void main(String[] args) {         System.out.println(Q26.q26.ans);     } } class Q26 {     public static Q26 q26;     public int ans;     private static final int var1;     private static int var2;      static {         q26 = new Q26();         var1 = 5;         var2 = 7;     }      public Q26() {         ans = var1 + var2;     } } 

So don't be fooled into thinking the keywords you use to declare variables ensures some specific execution order!

like image 32
Richard JP Le Guen Avatar answered Sep 30 '22 22:09

Richard JP Le Guen