10

This is the code that I've written.

int num;
try {
    num=100;
    DoSomething();
    System.out.println(num);
} catch(Exception e) {
    DoSomething1();
} finally{
    DoSomething2();
}
System.out.println(num); // Error Line

I get an error 'The local variable num may not have been initialized' on the error line that I've mentioned. On removing the catch block the error goes away. What is wrong here? Am I doing something incorrect?

0

7 Answers 7

11

If there is an exception thrown in your try block, then the variable num may indeed not have been initialised. If you include the catch block, then execution can continue to the error line regardless, and thus the compiler reports the error you state.

If you remove the catch block, then execution will only reach the "error line" if there has been no exception, and in this case, the variable will have been initialised within the try.

(I'm assuming you already know about the need to intialise local variables before using them, and have focused on the behaviour you noticed with the catch block...)

Sign up to request clarification or add additional context in comments.

5 Comments

Yes I'm aware of that , what made it interesting was the fact that removing catch block made the error go away.
@gizgok David answered this when he said: "If you remove the catch block, then execution will only reach the "error line" if there has been no exception, and in this case, the variable will have been initialised within the try." +1 btw
@david-m "If there is an exception thrown in your try block, then the variable num may indeed not have been initialised." How? The assignment is the first statement in the try block, so it is impossible for num not to be initialised. It's just the compiler which doesn't know this fact.
@dogbane What if the initialization was done like this: num=getNumberAndThrowRuntimeException()? The compiler, you and I will all be unsure in this case!
@dogbane Using Thread.stop(Throwable) can lead into a state where num is in fact not initialized when reaching code after try-catch-finally in the given example.
3

Exception handling can confuse the compiler. In this case, you know that an exception cannot possibly be thrown BEFORE the variable num is set, but the compiler doesn't know this.

The compiler thinks that an exception might be thrown before num has been set in which case num would not have been initialized when you try to print it outside the try-catch block.

1 Comment

You don't know that the assignment cannot possibly not run. See @FabianBarney's example for one case.
3

In Java you must init local vars. This is not guaranteed when you've these catch blocks since an exception may be thrown before init the local var in try block and you do not init the var in the catch block. Therefore the local var may not have been initialized after try-catch-finally block.

When you remove the catch block then the var is initialized after try or an exception is thrown and the code after try-block never get executed.

You've following possibilities to fix this:

  • init var before try-block
  • init var in try-blocks and catch-blocks
  • init var in finally block
  • init var only in try-block, but do not catch exceptions

The local var is not guaranteed to be initialized even when var init is the first thing you do in try-block. For example the executed thread can be stopped with Thread.stop(Throwable) after entering try-block but before var init. When this happens then the var is not initialized but catch-finally is executed and the code after try-catch-finally as well.

Here's an example to show what I mean:

public static void main(String[] args) throws InterruptedException {
    Thread thread = new MyThread();

    thread.start();
    Thread.sleep(100);
    thread.stop(new Exception());
}

private static class MyThread extends Thread {

    @Override
    public void run() {
        int num = -1;

        try {
            Thread.sleep(600); //just to hit the thread at the right point
            num = 100;
            System.out.println("blub");
        } 
        catch (Exception e) {
            System.out.println("catch");
        }
        finally {
            System.out.println("finally");
        }


        System.out.println(num);
        System.out.println("after all");
    }

}

This code prints out:

catch
finally
-1
after all

1 Comment

Example > explanation
2

You have putten num = 100 inside yout try block, the compiler assumes that an error may occur before num = 100 is reached. Thus, when you enter in the Catch bloch, for the compiler, he only sees int num which gives you the Variable not initialized error.

1 Comment

@Rosdi For the compiler, any error can occur. JVM planting, Internal error generated, ...
2

Local variables in Java are not initialized automatically. So you need to initialize it before use them.

int num=0;
try
{
  .. 
}
...

Fore more info read - Definite Assignment (JLS - 16.2.15 try Statements)

7 Comments

But he IS initializing it at num=100; The execution path also has no branching (no if else statement). So java should know that num is 100.
@Rosdi - That is inside the try block.
I know about the initialization part, I'm more interested in how the removal of catch block leads to no error.
Not necessarily. There might be some nasty exception before the assignment is finished.
@gizgok - catch block will be executed when an exception raised/throw where as finally block always executes when the try block exits.
|
1

I happened to have blogged about this yesterday http://vanillajava.blogspot.com/2012/01/odd-case-of-initialization.html

In short, the compiler doesn't know if the variable has been initialized inside a try/catch, even in the most trivial case. For this reason, it complains the variable might not have been initialised.

Interestingly, if you make the variable final and try to set it after the try/catch block the compiler will complain it might have been initialized.

5 Comments

,very interesting introducing the final aspect to the variable. Why does this happen? Any ideas?
You can't set a final variable if it has been initialized and after a try/catch block it may or may not be initialized. The compiler just has no idea.
There is the evil with Thread.stop(Throwable) that can lead into a state where the local var is in fact not initialized in the given example.
In theory yes. However once the code is optimised to native code, I believe it has to reach a safe-point to trigger such an exception. IMHO Thread.stop() is only "safe" when used on the current thread.
I am with you here. Just wanted to show that it is not as trivial as it looks like. And there are execution branches may lead into a state where the compiler is right about the "may not have been initialized".
0

The problem is that num is not initializated, int num = -1; And the error will go away ;)

3 Comments

But the assignment num=100 is executed before any exception can be thrown. So the catch block would always be executed after the assignment.
As the @AVD said "Local variables in Java are not initialized automatically"
Yes, but the variable will be initialized before it is accessed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.