Instance initializer against private members

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 the error: -

 b = new Test5(){{ value = 1 ;}}; 
<static variable

cannot refer to a static context.

The double-bound idiom claims that the second curly brace is the initializer for an instance of an anonymous class. So why can't it initialize a private member variable?

+4
source share
3 answers

Line

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

instantiates an anonymous class that extends Test5 . However, since value is private, an anonymous class cannot access the instance variable of its superclass.

Since there is no variable called value visible to the anonymous subclass of Test5 , the compiler is looking for an alternative in the following area. In this case, the next area relates to the static method main . The compiler detects the Test5 instance Test5 , and it issues a warning because the instance variable cannot refer to the static context.

Here you have two alternatives:

  • Or make the instance variable available to the anonymous class: protected int value;

  • or make the variable available for the static method main : private static value int;

I take it from your question that the first alternative is what you really want to do.

@Tom: The problem is not that the static area is scanned first. If that were the case, then alternative (1) would not work, because the value instance variable is still found and still cannot be specified.

@Ken: Your instanceMethod() does not do what you expect from this! Take a look at the following code:

 class Test5A { private int value; public void instanceMethod() { Test5A a = new Test5A() {{ value = 1; }}; // (A) System.out.println(this.value); System.out.println(a.value); } public static void main(String[] args) { new Test5A().instanceMethod(); } } 

This sample code mimics the behavior of your class. If you compile and execute it, you will see that the output is "1 0".

While the initializer of the instance of the anonymous subclass in (A) looks like it assigns one instance of the instance of value , this variable is actually visible only in the superclass of the anonymous class. Instead, in line (A), the only visible variable called value is the instance variable of the Test5A instanceMethod() that instanceMethod() called on. Therefore, it changes to one.

Now increase the visibility of value :

 class Test5B { protected int value; public void instanceMethod() { Test5B a = new Test5B() {{ value = 1; }}; System.out.println(this.value); System.out.println(a.value); } public static void main(String[] args) { new Test5B().instanceMethod(); } } 

This time the output will be "0 1". value instance variable inherited by an anonymous subclass, and its visible to its instance initializer. Therefore, one is assigned to the correct instance variable.

+5
source

Since you are trying to set a value value field that belongs to the original Test5 class, and an instance of this class is not available in a static context. Consider the 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); } } 

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

+1
source

The difference is to create an anonymous subclass in the instance context compared to the static context. For comparison:

 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; } }; } } 

Comment lines are not compiled. The ones for IsStatic are simple enough to understand, but the difference between the anonymous classes in instanceMethod and the static main more subtle.

Please note that private really has the effect of "visible only inside the top-level class" and not "visible only inside this class". (As far as I remember, the latter is the actual mechanism at the JVM level, and the way to get the same effect is to synthesize access methods.) How NotStatic can access priv .

It seems that the difference is that when you create an anonymous subclass in a static context, it is not considered "private". Someone more familiar with JLS can clarify.

+1
source

All Articles