简体   繁体   中英

Local variable might already have been assigned

I know there are a couple of questions on stackoverflow dealing with the problem of already initialized variables but I could not find anything answering my question with regards of local variables. Consider the following excerpt:

public class Test {


    public static void main() {
        final int i;

        try {
            i = computeI();
        } catch (Exception e) {
            i = 5;
        }
    }


    private static int computeI() throws Exception {
        return 3;
    }
}

The java compiler (openjdk-8-jdk) tells me i = 5 Variable i might already have been initialized but there is no way where i could have been assigned.

Question : Is there a way how i could have been initialized that a do not know of (since it's a local variable another thread cannot interfere to my knowledge). If not, why does the compiler issue this warning?

Java compiler follows Java Language Specification.

Your question is answered by the following parts of the spec:

https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4

https://docs.oracle.com/javase/specs/jls/se7/html/jls-16.html#jls-16.2.15

Basically there are no rules describing types of Exceptions that you catch and location of assignment within try block.

Also imagine if an Error happened inside try block (will not be caught by catch Exception), then i will still be unassigned after try statement. So even if the compiler was smart enough to see that i is unassigned in the catch block it would still need to complain about unassigned final variable.

The compiler isn't as clever as you think. Although you and I can infer that i could only possibly have been set in one place, it doesn't spot that and hence all it sees is two assignments to i.

You can get around it by using a temp variable (as in my answer to this post ).

No, there is no way that the variable could be assigned. However, the compiler only has limited deduction capabilities (and apparently they fail in this case), hence the might .

In this case there is no way that i variable could have been initialized when the catch block is executed, but the compiler isn't smart enough to understand, it doesn't spot distinction between one statement or multiple statement inside a try block .

Anyway I would prefer to rewrite your code using a simple variable(not a constant) and assigning it to default at the beginning in this way :

    int i = 5;

    try {
        i = computeI();
    } catch (Exception e) {
        //Exception handling 
    }

My personal suggestion is : never use try-catch in place of if statements and standard control flow constructs .

As the variable you are trying to assign is final.. In a specific condition for a normal flow, compiler will not let you assign values to a final field twice.. But if you can keep that inside a condition, compiler is showing no error.

for ex:

if (true) i = computeI(); else i =5;

当我们有多个捕获块和/或最终有多个捕获块时,这是有道理的。

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