在这种情况下,您在设置后不使用 foo 变量,因此 JVM 完全忽略该变量甚至是合法的,因为它从未使用过并且不会改变程序的结果。
但是,这在调试模式下不太可能发生。
在您的情况下,只要 foo 在范围内或者您持有对它的引用(包括 try/catch 块之后的部分),它就不应该被 GC 处理。
编辑
实际上,我得到的行为与您在 Netbeans 7.1.1 和 Java 7.0_03 中描述的行为相同......
一个问题可能是因为您没有将默认值设置为foo
,所以您不能在 try/catch 块之后使用它(它不会编译)。
字节码
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String bar
2: astore_1
3: iconst_5
4: istore_2
5: goto 9
8: astore_2
9: iconst_3
10: istore_2
11: return
String foo = null;
用作第一条语句,在这种情况下,调试器会看到 try/catch 块之后的值:
public static void main(java.lang.String[]);
Code:
0: aconst_null
1: astore_1
2: ldc #2 // String bar
4: astore_1
5: iconst_5
6: istore_2
7: goto 11
10: astore_2
11: iconst_3
12: istore_2
13: return
我不是字节码专家,但他们看起来和我很相似......
结论
我个人的结论是,要让调试器显示 的值foo
,它必须运行foo.toString()
某种类型的 a,这在 catch 块之后不是有效的语句,因为foo
可能尚未初始化。在该部分添加 aSystem.out.println(foo)
是不合法的(不编译)。调试器对于值是什么和显示有点迷失null
。
要说服自己这与 GC 无关,可以尝试以下示例:
public static void main(String[] args){
String foo;
char[] c = null;
try {
foo = "bar";
c = foo.toCharArray();
int yoo = 5; //1
} catch (Exception e) {
}
int foobar = 3;//2
}
在线上foobar
,您可以看到它c
成立bar
,但 foo 显示为null
. 所以字符串仍然存在,但调试器无法显示它。
更有趣的例子:
public static void main(String[] args){
String foo;
List<String> list = new ArrayList<String>();
try {
foo = "bar";
list.add(foo);
int yoo = 5; //1
} catch (Exception e) {
}
int foobar = 3;//2
}
就foobar
行了,foo
显示为null
,但list
包含"bar"
...很好。