I was preparing for Java OCA certification where I came across a similar question like that of the following one:
public class TestClass {
final int i;
public static void main(String[] args) {
TestClass t = new TestClass();
System.out.println(t.i);
}
}
As per Java, the instance and static variables are given default values. Surprisingly, this was error that was shown in my console:
error: variable i not initialized in the default constructor final int i;
Why wasn't i assigned a default value above?
Assigning default value to the final variable would defeat the entire purpose of making a variable final in the first place.
final would mean that you can't change the value once assigned.
If a default value is given to final variable then you would never be able to set the value of the variable to something else (even for the first time).
It's defined this way in the Java Language Specification:
Chapter 16. Definite Assignment
Each local variable (§14.4) and every blank final field (§4.12.4, §8.3.1.2) must have a definitely assigned value when any access of its value occurs.
[...]
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.
Where the term "blank final field" refers to a final field with no value or initializer, and "definitely assigned" means that the field will be assigned to no matter what:
The idea behind definite assignment is that an assignment to the local variable or blank final field must occur on every possible execution path to the access. Similarly, the idea behind definite unassignment is that no other assignment to the blank final variable is permitted to occur on any possible execution path to an assignment.
Aside from throwing an error by specification, there's logical reasoning behind the decision. There's no point in having a default value for a blank final field. In your case, the blank final is an integer, and it would just be given 0 and you wouldn't be able to change it. What would the use of the variable be?
Also, if a final variable is not explicitly given a default value, why not initialize it in the first place? You can't reassign to it later since a default value would already be given, so why not initialize it now?
Error message is misleading since it can be initialized with default value:
class FinalTest{
final int x = printXAndInitializeIt();
private int printXAndInitializeIt(){
System.out.println("x before initialization = "+x);
return 1;
}
public static void main(String[] args) {
FinalTest ft = new FinalTest();
System.out.println("x after initialization = "+ft.x);
}
}
Output:
x before initialization = 0
x after initialization = 1
But even if there is default value final variable expects explicit initialization, since in most cases lack of initialization is caused by mistake. This error could be changed to warning, but I am guessing that Java designers though that "better safe than sorry".
It's not that final fields aren't initialized to the default value — in fact they sort of are, though you'll only observe the fact if you're doing some silly stuff — but that you're required to explicitly initialize them exactly once (either as part of the declaration, or in an initializer block, or in every single constructor).
To understand the motivation for this, consider the following code:
public class Foo {
private final int mValue;
public Foo(final boolean shouldSet) {
if (shouldSet) {
mValue = 1;
}
}
// ...
}
If the field weren't final, then the compiler would infer an implicit = 0 at the end of its declaration; but with a final field that's not always valid . . . and in the above example, the compiler can't even tell beforehand whether it will be valid or not. So the compiler sidesteps the issue by never inferring an implicit = 0, and requiring explicit initialization.
Why didn't it assign a default value in the above case ? Can anyone
explain!
if a default value were to be provided then you wouldn't be able to change the value of it. when the final keyword is used with variables it means once the variable is assigned, it cannot be re-assigned.
Wikipedia:
A final variable can only be initialized once, either via an
initializer or an assignment statement. It does not need to be
initialized at the point of declaration: this is called a "blank
final" variable. A blank final instance variable of a class must be
definitely assigned in every constructor of the class in which it is
declared; similarly, a blank final static variable must be definitely
assigned in a static initializer of the class in which it is declared;
otherwise, a compile-time error occurs in both cases. (Note: If the
variable is a reference, this means that the variable cannot be
re-bound to reference another object. But the object that it
references is still mutable, if it was originally mutable.)
further reading:
Definite Assignment
Related
Consider a static variable, for example:
private static int x;
If we try printing its value in the main method, it will be 0. So the variable is initialised. Now consider if the variable is final:
private static final int x;
This is not possible; why? We have to initialise it like private static final int x = 2;, or using a static initialiser like:
static {
x = 2;
}
A static variable is initialised by default; so why is there a compilation error if the variable is also final?
In principle the language could let you declare a static final field and have it take its default value, but in practice if you fail to give an explicit value for a static final field then it is almost always by mistake. So the compiler gives you an error here because
This code does something you almost certainly didn't want it to do (or, fails to do something you almost certainly did want to do), and
The default value will be something trivial like 0 or null, so if using that value is what you intended, then the inconvenience imposed on you is minimal; you just have to write static final int x = 0; instead of static final int x;.
In fact, being forced to write = 0 or = null explicitly makes your code easier to read, understand and maintain. Keep in mind that most code will be read hundreds or thousands of times more often than it is written, so you are actually saving time by being more verbose and explicit.
Paragraph from Oracle Documentation:
The final modifier indicates that the value of this field cannot change.
For example, the following variable declaration defines a constant named PI, whose value is an approximation of pi (the ratio of the circumference of a circle to its diameter):
static final double PI = 3.141592653589793;
Constants defined in this way cannot be reassigned, and it is a compile-time error if your program tries to do so. By convention, the names of constant values are spelled in uppercase letters. If the name is composed of more than one word, the words are separated by an underscore (_).
Edit:
Please, check the java language specification. The answer to your question is there.
NOTE: The static keyword on your question title can be removed because you should initialize all final variables and not only static final ones.
All final variables should be explicitly initialized or at the point of declaration or in every constructor of the class in which it is declared ( in this case it is named blank final variable ). This because a final variable value can't be changed after first assignment. So language raises warning to implicitly assignments to final variables to drive developer to explicitly assign a value ( even if it is the default one like '0' for Integers ).
Moreover in the specific case of a "static final" variable you can also assign the value in a static initializer of the class in which it is declared.
I'm indebted to this answer for the idea.
The following code compiles, but certainly shouldn't. It uses the value of x before it's been initialised. If you remove the StaticAssign. qualifier then it no longer compiles.
public class StaticAssign {
public static final int x;
static {
System.out.println(StaticAssign.x);
x = 5;
}
public static void main(String[] args) {}
}
On my machine, this consistently prints 0. If I change the type of x to String, it consistently prints null.
The question is: will it definitely print 0 or null, or might it access uninitialised memory and print out something else?
And even if this code gets through the compiler, why isn't it picked up by the JVM?
Is there a way to do nasty things based on this?
It actually has been initialized. Variables in the global scope are initialized automatically. Variables of Object type will be initialized to null primitive like int will be initialized to 0. A variable declared not in the global scope must be initialized ie. declared in a method. Another problem is declaring it as final this is telling the compiler it must be explicitly initialized. So by adding the x=5 you are bypassing the compiler error saying it must be explicitly initialized. When you access it before this line at run-time it is initialized to 0 like any other primitive int type variable in the global scope.
This is due to the way in which the classes are loaded.
First the class StaticAssign definition is loaded and the fields are initialized to default values:
StaticAssign.x = 0;
Then the initalization block is executed.
System.out.println(StaticAssign.x);
x = 5;
There is a reference to StaticAssign.x, the current class. As recursive initialization attempts are simply ignored, value of x is still 0.
This means that:
System.out.println(StaticAssign.x)
is valid because StaticAssign.x is a reference to field of an allready loaded class.
But if yo do:
System.out.println(x)
then x is a reference to a final uninitalized field.
On the other hand, you never will access uninitialised memory. When the class definition is loaded variables are initialized to default values, before the initalization block is executed.
EDIT:
There is a nice video "Elvis Lives Again" from Java Puzzlers that shows this much more better than I can explain
I wanted to understand what am missing in the usage of final variable. I tried googling a lot about this strange (to me at least) behavior, and would love to know what happens behind the scenes.
Java Specification says:
A variable can be declared final. A final variable may only be assigned to once. Declaring a variable > final can serve as useful documentation that its value will not change and can help avoid programming > errors.
It is a compile-time error if a final variable is assigned to unless it is definitely unassigned (§16) > immediately prior to the assignment.
A blank final is a final variable whose declaration lacks an initializer.
Now consider the following code:
public class Sample {
private final int a;
private final Object object1; // compile error that object1 is not initialized
private final Object object2 = null;
public Sample(int value) {
System.out.println(this.a);
a = value;
System.out.println(this.a);
object2 = new Object(); // Compile error that it shouldn't change
}
}
Below are my observations:
In line 2 public final int a the JVM will assign a default value of 0 to a
Which is why the first print statement in the Constructor prints value "0"
Then we are trying to modify the default value to a "value" (a=value) that is passed to the constructor
It allows to change the value, and then from the next assignment the compiler will give an error.
While in the case of Objects private final Object object1 it gives a compile time error that object1 is not initialized. Though by default JVM assigns a "null" value for instance members by default.
Once a value for the object is assigned private final Object object2=null then it works pretty much as expected.
Now can someone answer, why the compiler behaves differently with the default assignments to primitives and objects when final keyword is used?
In case if you feel if this a dumb question am sorry, but I request you to point to a source where I can get the answer.
Thanks
Sharath
In line 2 public final int a the JVM will assign a default value of 0 to a
That's what the JVM does. That's not what the compiler does - it's not an assignment within the source code. It's just the value the variable has before it's assigned any other value.
The JLS doesn't say that you can't observe the value of a final variable changing within a constructor. It says that you must assign to a final variable exactly once. That's exactly the case for a - the only assignment to it is within the constructor, so it's fine.
There's no difference between primitives and classes here - if you explicitly assign a value of 0 to a in the field declaration, you'll see the same error when you try to assign to a within the constructor.
Why aren't default values assigned to the variables, that haven't been initialized within a Class with main function???
class Test {
public static void main(String[] args) {
int x;// x has no default value
String y;// y has no default value
System.out.println("x is " + );
System.out.println("y is " + );
}
}
Whereas the default values get assigned in case the variables remain uninitialized in a class without any main function.
class Student {
String name; // name has default value null
int age; // age has default value 0
boolean isScienceMajor; // isScienceMajor has default value false
char gender; // c has default value '\u0000'
int x;
String y;
}
Be aware that the code in the question represents different situations. In the first case, the variables are local and exist inside the main() method. In the second case you're declaring instance attributes, not local variables.
In Java, only the attributes are initialized automatically with default values. In all the methods, even in the main() method, you must explicitly provide an initialization value for the variables declared locally inside the method.
This is explained in the Java Language Specification, section §4.12.5:
Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10)
Each method parameter (§8.4.1) is initialized to the corresponding argument value provided by the invoker of the method (§15.12)
Each constructor parameter (§8.8.1) is initialized to the corresponding argument value provided by a class instance creation expression (§15.9) or explicit constructor invocation (§8.8.7)
An exception parameter (§14.20) is initialized to the thrown object representing the exception (§11.3, §14.18)
A local variable (§14.4, §14.14) must be explicitly given a value before it is used, by either initialization (§14.4) or assignment (§15.26), in a way that can be verified using the rules for definite assignment (§16)
To see several reasons why local variables are not initialized automatically, please take a look at this previous question.
The basic reason is that, in order to catch a common programmer error, the Java authors decided to ensure that every variable is assigned before it is used. However, it is not possible to enforce this for fields, so they had to spec default values for fields.
You do get an error if you use a field in a constructor before it is initialized, but there is no way for the compiler to prevent this:
class C {
int f;
C() {
init();
}
void init() {
System.out.println(f);
}
}
When the JVM is creating the new object instance, it has to allocate memory for the attributes because they are part of the class itself. The mere existence of a Java primitive int requires 4 bytes of memory to be allocated, whereas an Integer can be set to null since it's an object. That's why classes must have their attributes set to something upon being initialized.
Reading the value of a variable before it has been given a value is a common source of bugs. Forcing you to assign a value before using a variable makes programs safer: you'll know you'll get the value you expect and not some default value just because you didn't anticipate a certain program flow.
Unfortunately the liveness analysis that implementing this needs can only be done for local variables, and you can access instance fields before the program has initialized them with a value. To avoid unpredictable behavior the JVM initializes instance fields to default values.
Why must a final variable be initialized before constructor completes?
public class Ex
{
final int q;
}
When I compile this code I get error like this
err:variable q might not have been initialized
The official reason is that it is defined by the Java Language Specification 8.3.1.2:
A blank final instance variable must be definitely assigned at the end of every constructor of the class in which it is declared; otherwise a compile-time error occurs.
A blank final is a final variable whose declaration lacks an initializer (i.e. what you describe).
The value of a final variable can only be set once. The constructor is the only place in the code for a class that you can guarantee this will hold true; the constructor is only ever called once for an object but other methods can be called any number of times.
Because final prevents you from modifying variables, but it has to be initialized at some point, and the constructors is the right place to do so.
In your case, it would be called a blank final because it is not initialized when declared.
A final variable must be initialized at the declaration or in a constructor.
If it has not been initialized when the constructor returns, it may never be initialized, and may remain an uninitialized variable. The compiler cannot prove it will be initialized, and thus throws an error.
This Wikipedia excerpt explains it well:
A final variable can only be initialized once, either via an initializer or an assignment statement. It does not need to be initialized at the point of declaration: this is called a "blank final" variable. A blank final instance variable of a class must be definitely assigned at the end of every constructor of the class in which it is declared; similarly, a blank final static variable must be definitely assigned in a static initializer of the class in which it is declared: otherwise, a compile-time error occurs in both cases. (Note: If the variable is a reference, this means that the variable cannot be re-bound to reference another object. But the object that it references is still mutable, if it was originally mutable.)
The final keyword applied to a field has one of two effects:
on a primitive, it prevents the value of the primitive from being changed (an int can't change value)
on an object, it prevents the "value of the variable", that is, the reference to the object, from being changed. That is to say that, if you have a final HashMap<String,String> a, you will only be able to set it once, and you won't be able to do this.a=new HashMap<String,String>(); again, but nothing keeps you from doing this.a.put("a","b"),s since that doesn't modify the reference, only the content of the object.
The final modifier prevents your from changeing the variables value, hence you have to initialize it where you declare it.
The language specification contains specific guarantees about the properties of final variables and fields, and one of them is that a properly constructed object (i.e. one whose constructor finished successfully) must have all its final instance fields initialized and visible to all threads. Thus, the compiler analyzes code paths and requires you to initialize those fields.
If an instance variable is declared with final keyword, it means it can not be modified later, which makes it a constant. That is why we have to initialize the variable with final keyword.Initialization must be done explicitly because JVM doesnt provide default value to final instance variable.Final instance variable must be initialized either at the time of declaration like:
class Test{
final int num = 10;
}
or it must be declared inside an instance block like:
class Test{
final int x;
{
x=10;
}
}
or
it must be declared BEFORE constructor COMPLETION like:
class Test{
final int x;
Test(){
x=10;
}
}
Keep in mind that we can initialize it inside a consructor block because initialization must be done before constructor completion.
Final modifier does not allow to change your variable value. So you need to assign a value to it at some place and constructor is the place you have to do this in this case.
The moment the constructor completes execution, the object is 'open for business' - it can be used, its variables can be accessed.
The final keyword on a variable guarantees that its value will never change. This means, if the value is ever read, you can be sure that the variable will always have that value.
Since the variable can be accessed (read) at anytime after the execution of the constructor, it means it must never change after the constructor has executed - just it case it has been read.
Thus, it must, by then, have been set.