ljnelson noted at 'http://weblogs.java.net/blog/jst/archive/2008/10/the_better_comp.html' that it is enough to make the variable final and the problem goes away. True, final helps, however the same code without final works as well. This very likely means that the compiler puts the variable into the topmost block where it is guaranteed to be fully initialized. That is why we need a hint warn about declaration of non-fully initialized variables.
1 package org.apidesign.gc;
3 import java.lang.ref.Reference;
4 import java.lang.ref.WeakReference;
6 import org.netbeans.junit.NbTestCase;
7 import static org.junit.Assert.*;
9 // BEGIN: compiler.surprises.intro
10 public class CompilerSurprisesTest {
11 Reference<String> cache;
13 public String factory() {
14 String value = new String("Can I disappear?");
15 cache = new WeakReference<String>(value);
20 public void checkThatTheValueCanDisapper() {
21 String retValue = factory();
23 assertGC("Nobody holds the string value anymore." +
24 "It can be GCed.", cache);
26 // FINISH: compiler.surprises.intro
28 // BEGIN: compiler.surprises.error
30 public void obviouslyWithoutClearingTheReferenceItCannotBeGCed() {
31 String retValue = factory();
32 // commented out: retValue = null;
33 assertNotGC("The reference is still on stack." +
34 "It cannot be GCed.", cache);
36 // END: compiler.surprises.error
39 // BEGIN: compiler.surprises.surprise
42 public void canItBeGCedSurprisingly() {
47 assertGC("Can be GCed, as retValue is not on stack!!!!", cache);
49 // END: compiler.surprises.surprise
52 // BEGIN: compiler.surprises.fix
55 public void canItBeGCedIfInitialized() {
56 String retValue = null;
60 assertNotGC("Cannot be GCed as retValue is not stack", cache);
62 // END: compiler.surprises.fix
64 // BEGIN: compiler.surprises.fix.init
65 @Test public void properInitializationFixesTheProblem() {
72 assertNotGC("Cannot be GCed, now the retValue is on stack", cache);
74 // END: compiler.surprises.fix.init
76 // BEGIN: compiler.surprises.fix.final
77 @Test public void properUsingFinalFixesTheProblem() {
78 final String retValue;
84 assertNotGC("Cannot be GCed, now the retValue is on stack", cache);
86 // END: compiler.surprises.fix.final
89 private static void assertGC(String msg, Reference<?> ref) {
90 NbTestCase.assertGC(msg, ref);
93 private static void assertNotGC(String msg, Reference<?> ref) {
95 NbTestCase.assertGC("Cannot be GCed. " + msg, ref);
100 fail(msg + ref.get());