Why must a final variable be initialized before constructor completes? - java

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.

Related

Why aren't final instance variables given default values?

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

Accessing an uninitialised static field in Java

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

why variable defined in a class is not a local variable but instance variable in java?

According to the doc Local variables in java are declared in methods, constructors, or blocks.
In the below Class A isn't x a local variable too since it is in blocks({}) i know they are called as instance variable but i am confused? If yes Access modifiers cannot be used for local variables but i am sure i can add public private protected ? It also says that local variable are stored in stack but as per the below code x will be stored in heap right since they are part of the instance?
class A{
private int x = 5; // Isn't this a local varibale too since it is in blocks
}
.
class A{
public void function(){
int x = 5; // this is a local variable since it is declared in a function
private int x2=5; // Error Access modifiers cannot be used for local variables
}
}
In the below Class A isn't x a local variable too since it is in blocks({})
No. It's not in a block. It's in a class declaration, but that's not a block as such. "Block" isn't synonymous with "text in braces".
To be a bit clearer, local variables are declared in:
Methods
Constructors
Static initializers
Instance initializers
If you look at the production for a class declaration, that's not a Block (unlike the production for static initializers and instance initializers).
In the below Class A isn't x a local variable too since it is in
blocks({})
Your x is not a local variable, it's an instance variable. Block means, instance initialization block or static block or try catch block.
Access modifiers cannot be used for local variables but i am sure i
can add public private protected ?
It doesn't make sense to have access modifiers to method local variables, since, method local variable can only be accessed inside the method.
I'm not entirely sure where you are reading. Local variables are values declared inside a method.
There is no special keyword designating a variable as local; that determination comes entirely from the location in which the variable is declared — which is between the opening and closing braces of a method.
Taken from here.
A local variable is a variable that has a local scope and is generally not expected to last a long time.
If you declare a variable inside a method, that variable will only be relevant while that method is being executed, and after the method finishes the variable will be discarded.
An instance variable is a variable that is bound to an instance of "something" and is generally considered to last as long as that "something" lasts.
If you declare a variable inside a class, then when you create a new instance of the class the variable will also be created and pinned onto the class. The variable will be there as long as the instance object of the class that you created exists, if you decide to discard the instance of the class you made, then the instance variable gets discarded as well.
Hope this was intuitive.

Final attribute of a final datatype?

What happens when I declare something like:
public static final String forma = "Rectangular";
Isn't it redundant? Being String a final class, what would it change not setting forma as final? For static, I think it is not making any change.
final make sure reference is not assigned to new value.
If you don't make it final, it is valid to assign some other value to forma (or) you can do some operation on Rectangular and assign results back to forma
See String is a final class,and final keyword makes references final not object final.
Final object means it can't be altered but final reference means it can't be assigned to another object after first assignment.
Being final means you can not modify the object String s="hello", "hello" is the string object and it cant be modified, but about s if its a non-final reference and i do thing like:s=s.concat("bing") then, "hello" is taken can concatenated with "bing" object and then assigned to s means "hello" and "bing" objects are not modified they lost their references and non-final reference s is now referring to a new object "hellobing".
I surely wanna help you more if you find this interesting.
For object-types 'final' modifier means that REFERENCE to this object cannot be changed, not it's value!
Isn't it redundant?
No, it is not redundant. It is constant. Every keyword of this statement has meaning. final make it immutable, static make it class variable and public make it globally accessible.
The final keyword is heavily overloaded, and means very different things in different contexts:
On fields and local variables, it indicates that the content of a reference cannot be changed. (This is different from immutability.)
On classes, it indicates that the class cannot be subclassed.
On methods, it indicates that the method cannot be overridden in subclasses.

difference between final and static variables with reference to their use in innerclass

this is regarding final variables in inner class, but instead of declaring variable as a final if we declare variable as static out side the method ,assuming that the method is static. Then what is the difference between declaring as static outside method or final inside method to be accessed in innerclass. will they make any difference or they function similarly. Which one is the best one to use. I will be waiting for reply.
Thanks in Advance
static variables will keep their value across different instantiations of the inner class. Lets say you declare a static variable in inner class A and assign it the value 1 and then in the method call increment its value to 2. When another instance of this inner class is created it will have the value of A as 2.
In case of final variables you can assign the value only once when declaring (in your case i.e., declaring inside a method). What compiler does as a result of this is that it inlines the value i.e., wherever you this variable the variable is replaced with its value (since you cannot change its value).
I suggest using final variable wherever possible. but static has its won needs and usage depends on usage scenario.
Final variables are instance variables, whose values cannot be changed after it is initialized ( either in the c'tor or while declaring ).
But Static variables belongs to a class. This 'll be shared amoung all instances. So when you change the value of a static variable in an instance it gets reflected in all the instances.

Categories