emulated by a synthetic accessor method Monday, September 19, 2005

I stumbled across this warning while performing my regular cleansing the code base for wanings.
Being the first time I've seen it I felt the need for a bit of research.
This is generated by Eclipse and IBM WSAD when an nested class is trying to reference a private field in its containing class.
For example:

package demo;
public class Foo {
private String myFoo;

private class Bar {
private String myString;

void changeVal() {
myFoo = "bar";
}
}
}

To understand this, you have to remember that the inner class is compiled into a separate file. So, the compiler outputs two files: Foo.class and Foo$Bar.class into the same folder. Since a class cannot see the private member variables of another, the compiler generates an accessor method, and links to it.
Running javap -s -c -private demo.Foo yields:

Compiled from "Foo.java"
public class demo.Foo extends java.lang.Object{
private java.lang.String myFoo;
Signature: Ljava/lang/String;

public demo.Foo();
Signature: ()V
Code:
0: aload_0
1: invokespecial #11; //Method java/lang/Object."":()V
4: return

static void access$0(demo.Foo,java.lang.String);
Signature: (Ldemo/Foo;Ljava/lang/String;)V
Code:
0: aload_0
1: aload_1
2: putfield #19; //Field myFoo:Ljava/lang/String;
5: return

}

Here we can see the compiler generated the static method (with package level access) access$0(Foo foo, String s)
This is literally the equivalent of:

static access$0(Foo foo, String s){
foo.myFoo = s;
}

Disassembling Foo$Bar (javap -s -c -private demo.Foo) shows the method being called.

void changeVal();
Signature: ()V
Code:
0: aload_0
1: getfield #17; //Field this$0:Ldemo/Foo;
4: ldc #24; //String bar
6: invokestatic #30; //Method demo/Foo.access$0:(Ldemo/Foo;Ljava/lang/String;)V
9: return

This means the method changeVal() was changed from its original form to:

void changeVal(){
Foo.access$0(this$0,"bar");
}

Where this$0 is the instance of Foo that was sent to the constructor of the nested class Foo$Bar.
So, how do you make the original warning go away? Just change the access of the private variable to package level access (no access modifier).


<willCode4Beer/> posted at 12:36 PM

0 Comments:

Post a Comment

<<< This way to the egress