简体   繁体   中英

In Java, what exactly constitutes as “initializing a local variable”?

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"?

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.)

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:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM