Java compilation error for instance level Target variables and not setting for method level local variables
Why doesn't the java compiler give any kind of compile-time error for method-level local final variables when we don't initialize them?
(but it gives en error for final instance level variables when they are not initialized).
public class FinalKeyword
{
final int j; // error: the blank final field j may not have been initialized.
public static void main(String[] args)
{
final int k; // not giving any Compile time error!
}
}
source to share
Thing: once you change your method main()
to
final int k;//Not Giving any Compile time error
System.out.println(k); //different story now!
You will get the error k not initialized too!
Point:
- the compiler has to make sure that the other source code that is not showing right now ... is able to do
new FinalKeyword()
without issue. Thus, it cannot let you keepj
uninitialized. - but this method
main()
... even if another method calls this methodmain()
, that's ok. The method does nothing! In other words, it's not a problem to define a variable that is not used in the method! Because there is no way to access this variable!
The compiler should prevent you from getting into situations where you "stumble" over an uninitialized variable. When you call a method that has variables like this ... but never uses them - it just "doesn't care".
And with surprise: when we go with
public class FinalTest {
public static void main(String args[]) {
final int k;
}
}
and compile this; and then we use javap to get the decompiled bytecode:
public static void main(java.lang.String[]);
Code:
0: return
This is one of the rare cases where javac will optimize a little - by simply discarding unused variables. Bonus fun fact: even if you change my example to, k=5;
you'll find that the class file still only contains return
!
source to share
j
- class field. k
not. You need to initialize the final fields in the class constructor. Your class uses your implicit default constructor, which does not initialize fields.
The reason it doesn't give you a warning for a local variable is because you are not using it. If you were using an uninitialized local variable, you would get an error:
public static void main(String[] args)
{
final int k;
if (k < 5) {
// whatever
}
}
As to why the compiler is not smart enough to know that you are not using the field either, I'm not sure. This seems to be more complicated due to inheritance, access levels, etc.
source to share
In general, if the compiler is faced with a situation where final
it can be accessed uninitialized or specified during initialization, an error occurs.
The fields of the class final
must be initialized as someone can access them at any time. If it's private, protected, or public, other code can access the field directly, and they expect it to be initialized. Even if a field private
, someone can reflect it and try to access it, so the compiler shouldn't ignore it.
Local methods final
are internal to a method, and there is no way to reflect within a method without changing some bytecode, so the compiler shouldn't be that strict. Instead, the compiler does flow parsing control to display when a field is assigned and not assigned, and it will throw an error if it is used, or it might not, and will be contained if it is never used or is not used. definitely appointed.
void meth0() {
final String s;
// Compiler: s is never used; I don't care.
}
void meth1() {
final String s;
// s is definitely unassigned
if(something()) {
s = "something";
// s is definitely assigned
System.out.println(s);
} else {
// s is definitely unassigned
s = "other";
// s is definitely assigned
System.out.println(s);
}
// if-branch def. assigns s, else-branch def. assigns s
// Ergo: s is def. assigned
somethingElse(s);
// Compiler: control flow checks out; code is valid
}
void meth2() {
final String s;
// def. unass.
if(something()) {
s = "something";
// def ass.
}
// s is in undetermined state
// s = ""; // s may be assigned; error
// use(s); // s may not be assigned; error
// s is now totally unusable. Nice job breaking it, hero!
}
source to share