Reputation: 1484
say I have a piece of code in a local method
int a = 5, b;
and then some code to indirectly initialize B such as
if (true) b = 5; // legal
if (someBool) b = 10; else b = 7; // legal
if (false) b = 5; // illegal
illegal even though B will always be initialized
if (a > 10)
b = 4;
if (a <= 10)
b = 4;
My question is what are all of the exact circumstances in which a local variable can be legitimately considered "initialized"?
Upvotes: 3
Views: 97
Reputation: 156504
A local variable can be considered to be "initialized" if the compiler can easily deduce that every possible code path will lead through a path where the value has been set.
if(true)
can be determined to always run.if(false)
can be determined to never run.if/else
can be determined to run at least one of the branches, so you must assign the variable in each branch if you want it to be guaranteed initialized. Same principle applies for if/else if/.../else
switch
statements will either run one of the possible case
s, or will hit the default
case, so if you assign the variable in all of these places then it can be guaranteed initialized.The Java compiler doesn't bother checking all the possible values of each variable at various points in the method when making this determination, because variables are variable--they can change. However, if values can be considered constant then it can safely assume they won't change.
For example, the compiler doesn't care if you assign a variable and never change it in your code:
boolean val = true;
if(val) {
b = 5;
}
Debuggers and things make it possible for you to change the value of val
on-the-fly, so the compiler doesn't make any assumptions here. However, if you make val
constant, by declaring it final
and initializing it with a constant or literal value, then the compiler will treat it exactly the same as if you'd used the constant value in code.
final boolean val = true;
if(val) { // Same as if you'd said `if(true)`
b = 5;
}
Such constants can be chained, as well, and the compiler will simplify them to their constant values rather than maintaining the longer expressions and operators:
final int five = 5;
final int four = five - 1; // Same as `four = 5 - 1`, or `four = 4`
final boolean val = five > four;
if(val) { // Same as `if(5 > 4)`, or `if(true)`
b = 5;
}
For further reading, check out the Java Specs. (Hat tip to Radiodef for finding the right section.)
Upvotes: 4
Reputation: 85779
In this case:
if (false) b = 5; // illegal
The compiler throws an exception since if(false)
can be erased at compile time. It is futile to even analyze a block of code that won't be executed by any mean.
In this case:
int a = 5, b;
if (a > 10)
b = 4;
if (a <= 10)
b = 4;
The compiler cannot assure that the piece of code will be executed since a
can change its value. In this case, you can fix it by marking a
as final and assigning it a literal int value (which compiler can understand):
final int a = 5;
int b;
if (a > 10)
b = 4;
if (a <= 10)
b = 4;
But note that you can still break this code by giving final int a
a value that the compiler cannot determine:
final int a = foo();
int b;
if (a > 10)
b = 4;
if (a <= 10)
b = 4;
//...
int foo() {
return 5;
}
More info:
Upvotes: 0