为什么catch块会在Java中初始化变量时出错

时间:2012-01-05 10:21:07

标签: java

这是我写的代码。

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

我在我提到的错误行上收到错误'本地变量num可能尚未初始化'。在移除catch块时,错误消失。这有什么不对?我做错了吗?

6 个答案:

答案 0 :(得分:10)

如果try块中存在异常,则变量num可能确实尚未初始化。如果包含catch块,则执行可以继续到错误行,因此编译器会报告您说明的错误。

如果删除catch块,则执行只会到达"错误行"如果没有例外,在这种情况下,变量将在try内初始化。

(我假设您已经知道在使用局部变量之前需要初始化局部变量,并且专注于您在catch块中注意到的行为......)

答案 1 :(得分:3)

异常处理会使编译器混淆。在这种情况下,知道在设置变量num之前不可能抛出异常,但编译器并不知道这一点。

编译器认为在设置num之前可能会抛出异常,在这种情况下,当您尝试在try-catch块之外打印时,num不会被初始化。

答案 2 :(得分:3)

在Java中,您必须初始化本地变量。当你有这些catch块时不能保证这一点,因为在init块中初始化本地var之前可能抛出异常并且你没有在catch块中初始化var。因此,在try-catch-finally块之后,本地var可能尚未初始化。

删除catch块后,在try或抛出异常后初始化var,并且try-block之后的代码永远不会被执行。

您有以下可能性来解决此问题:

  • 在try-block之前的init var
  • try-blocks和catch-blocks中的init var
  • init var in finally block
  • init var仅在try-block中,但不捕获异常

即使var init是你在try-block中做的第一件事,也不保证本地var被初始化。例如,在进入try-block之后但在var init之前,可以使用Thread.stop(Throwable)停止执行的线程。当发生这种情况时,var不会被初始化,但是catch-finally会被执行,而try-catch-finally之后的代码也会被执行。

这是一个展示我的意思的例子:

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");
    }

}

此代码打印出来:

catch
finally
-1
after all

答案 3 :(得分:2)

Java中的局部变量不会自动初始化。所以你需要在使用之前初始化它。

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

更多信息阅读 - Definite Assignment (JLS - 16.2.15 try Statements)

答案 4 :(得分:1)

昨天我碰巧在博客上发表了这篇文章http://vanillajava.blogspot.com/2012/01/odd-case-of-initialization.html

简而言之,即使在最简单的情况下,编译器也不知道变量是否已在try / catch中初始化。出于这个原因,它抱怨变量可能尚未初始化。

有趣的是,如果你将变量设为final并尝试在try / catch块之后设置它,编译器会抱怨它可能已被初始化。

答案 5 :(得分:0)

问题是号码未初始化, int num = -1; 错误将消失;)