0

I'm trying to run this code:

class A {
  int x = 123;
  public void f(int x) {
    new Runnable() {
      public void run() {
        System.out.println(x);
      }
    }.run();
  }
  static {
    A a = new A();
    a.f(33);
  }
}

But it's giving me an error:

$ javac A.java && java A
A.java:6: local variable x is accessed from within inner class; needs to be declared final
        System.out.println(x);
                           ^
1 error

The x argument isn't final, so it shouldn't be accessible from the anonymous class, yet the code fails to compile. It looks like the println line is trying to use the x argument instead of the x field. Why? How can I tell it I want the x field?

Dog
  • 7,707
  • 8
  • 40
  • 74
  • 1
    @Makoto This is not a duplicate of that question. That question involves accessing non-final variables, not shadowing. – Jason C Mar 28 '14 at 03:12

1 Answers1

8

You can use

A.this.x

Since the anonymous Runnable class is an inner class of the A class.

The concept of shadowing determines that x in

System.out.println(x);

is referring to the local method parameter variable x, but that is not final so you can't access it within the anonymous class, not in Java 7 and below at least. You can in Java 8, which may be confusing.

Don't use the same name for your variables in the same compilation unit.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • Yep, that's it. Beat me to it. 1+ – Hovercraft Full Of Eels Mar 28 '14 at 03:01
  • @JasonC I'm sure there's one somewhere. People that ask don't usually know the names of the concepts involved so it is kind of hard to find. – Sotirios Delimanolis Mar 28 '14 at 03:14
  • @SotiriosDelimanolis Yeah, I found one right when you replied, a little down the "java inner shadowed" search result list. Not too obvious unless your search-fu is strong. *flex* – Jason C Mar 28 '14 at 03:16
  • What's a compilation unit? Got a link about the Java 8 change? – Dog Mar 28 '14 at 03:25
  • @Dog A compilation unit is a single file that gets compiled. So a single `.java` file. As for Java 8, see the tutorial on [Local Classes](http://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html) on `Accessing Members of an Enclosing Class`. I don't have the link to the JLS now. Please don't ask for it :|. I'll find it if you really want. – Sotirios Delimanolis Mar 28 '14 at 03:27