这是我写的代码。
int num;
try {
num=100;
DoSomething();
System.out.println(num);
} catch(Exception e) {
DoSomething1();
} finally{
DoSomething2();
}
System.out.println(num); // Error Line
我在我提到的错误行上收到错误'本地变量num可能尚未初始化'。在移除catch块时,错误消失。这有什么不对?我做错了吗?
答案 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之后的代码永远不会被执行。
您有以下可能性来解决此问题:
即使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
{
..
}
...
答案 4 :(得分:1)
昨天我碰巧在博客上发表了这篇文章http://vanillajava.blogspot.com/2012/01/odd-case-of-initialization.html
简而言之,即使在最简单的情况下,编译器也不知道变量是否已在try / catch中初始化。出于这个原因,它抱怨变量可能尚未初始化。
有趣的是,如果你将变量设为final并尝试在try / catch块之后设置它,编译器会抱怨它可能已被初始化。
答案 5 :(得分:0)
问题是号码未初始化, int num = -1; 错误将消失;)