variable r might not have been initialized

2019-06-16 17:08发布

问题:

There's a very simple program:

public class A {
    public static void main(String[] p) {
        final Runnable r = new Runnable() {
            public void run() {
                System.out.println(r);
            }
        };
        r.run();
    }
}

And this gives:

$ javac A.java 
A.java:6: variable r might not have been initialized
                System.out.println(r);
                                   ^
1 error
  1. Why?
  2. How can a Runnable reference a variable pointing to it?

(In the real code, there is one more level (a listener), and referencing via this does not work)

回答1:

In this case, you can use "this" to avoid the compilation error:

    final Runnable r = new Runnable() {
        public void run() {
            System.out.println(this); // Avoid compilation error by using this
        }
    };


回答2:

To answer your second question:

Runnable outer = new Object() {
   public final Runnable r = new Runnable() {
        public void run() {
            System.out.println(r);
        }
    };
}.r;
outer.run();

should work.

Here the compiler sees that r will have been initialized through the implicit constructor.

For your tiny example, it would be enough to move the final Runnable r outside the main method and say:

new A().r.run();


回答3:

In this case your new Runnable is being created before r, because of order of operations everything to the right side of an assignment operator is performed before the assignment. This means that r is not in scope when your Runnable is declared, and thus it doesn't know what it is inside the run method.



回答4:

There's no r variable in the scope of your run() method, you are trying to print out some value during it's initialization... That's why it "might not have been initialized".



回答5:

just use "this" in the Runnable in the place of "r" ))) works fine. Then you do not need to add the "outer" Runnable.



回答6:

The working code is:

public class A {
    public static void main(String[] p) {
        class RunnableHolder { Runnable r; };
        final RunnableHolder r = new RunnableHolder();
        r.r = new Runnable() {
            public void run() {
                System.out.println(r.r);
            }
        };
        r.r.run();
    }
}

So it is possible to "unfinal" a variable using an auxiliary object.

It looks like this construct (an auxiliary object whose fields may be accessed from a Runnable) is exactly what the designers of Java tried to disallow. :)



回答7:

public class A {
    private static Runnable r; 
    public static void main(String[] p) {
        r = new Runnable() {
            public void run() {
                System.out.println(r);
            }
        };
    }
}

This should work! And there is no r in the scope of run and thus it cannot be found in the anonymous implementation.



标签: java final