views:

171

answers:

3

I have the following code :-

public class Test5 {
    private int value ;
    public static void main(String[] args) {
        Test5 a, b;
        a = new Test5();
        b = new Test5(){{ value = 1 ;}};
    }
}

The following line shows an error :-

b = new Test5(){{ value = 1 ;}};

non-static variable cannot be referenced from a static context.

The double-brace idiom states that the second brace is the instance initializer of the anonymous class. So why cannot it initialize a private member variable?

+4  A: 
janko
No, it is actually accessible. javac does report the error as being about the static context, not the access modifier.
Tom Hawtin - tackline
Tom is right ! value is accessible.. and as mentioned, its the static problem being reported as the error !
Ajay
If I make value "protected" instead of "private", then the example of Ajay shows no warnings at all. I.e., the problem is that the anonymous class could not see the variable and, instead, the compiler assumed that a non-static variable was to be accessed from the context of main.
janko
If you try to compile the example and change the visibility of 'value' you'll see janko is right. A private value is not visible in a subclass...
pgras
Yes. I think. (Isn't it ugly?)
Tom Hawtin - tackline
+1 .. Hey.. thats right
Ajay
+1  A: 

Because you trying to set value value field which belongs to original Test5 class, and no instance of this class is avalible in static context. Consider following code

public class Test5 {
    private int value = 0;
    public static void main(String[] args) {
        (new Test5()).foo();
    }
    void foo(){
        Test5 b = new Test5(){

            {
             value = 1;
            }

        };
        System.out.println(value);
    }
}

output will be 1. If you want to set value of anonymous class you must reference it with this.value, but this will also give you a compile error because value is private.

Nikolay Ivanov
+1  A: 

The difference is creating an anonymous subclass within an instance's context versus a static context. Compare:

public class InnerClasses {
  int pack;
  private int priv;
  static private int stat;

  private class NotStatic {
    {
      pack = 1;
      priv = 1;
      stat = 1;
    }
  }

  private static class IsStatic {
    { 
      pack = 1;  // Static member class not tied to outer instance
      priv = 1;  // Ditto
      stat = 1;
    }
  }

  public void instanceMethod() {
    InnerClasses a = new InnerClasses() {
      {
        pack = 1;
        priv = 1;
        stat = 1;
      }
    };
  }

  public static void main(String[] args) {
    InnerClasses s = new InnerClasses() {
      {
        pack = 1;
        priv = 1;  // Anonymous subclass in static context
        stat = 1;
      }
    };
  }

}

The lines with comments do not compile. The ones for IsStatic are simple enough to understand, but the difference between the anonymous classes in instanceMethod and the static main is more subtle.

Note that private really has the effect of "visible only within the enclosing top-level class", and not "visible only within that class". (As I recall, the latter is the actual mechanism at the JVM level, and the way to get the former effect is by synthesizing accessor methods.) That's how NotStatic can access priv.

So apparently the difference is that when creating an anonymous subclass in a static context, it is not considered "enclosed". Someone more familiar with the JLS might be able to clarify.

Ken
Yes, your anonymous class in instanceMethod() CAN reference the priv instance variable. However, its not the variable you're probably expecting it to reference. Take a look at my extended answer.
janko