Access "This" from Java Anonymous Class

Access this from Java anonymous class

Container.this.select();

Why anonymous class can't access private methods and variables?

There is a confusion in that code about "inner class" and "anonymous class".

Notice you have 3 classes there:

  • Child
  • Hello
  • Hello$1: An anonymous class declared inside of Hello and whose parent is Child

The confusion in the code is about the latter:

  • Hello$1 is a subclass of Child
  • Hello$1 is an inner class of Hello

This means:

  • Hello$1 cannot access private fields from Child, as subclasses cannot access private elements of their super classes
  • Hello$1 can access private fields from Hello, as anonymous inner classes can access private elements of their enclosing classes

Check it more clearly in this code:

class Child {
private int a = 50;
}

public class Hello {
private int b = 60;

public void f()
{
Child c = new Child() {
public void f() {
// System.out.println("a = " + a); // This won't compile
System.out.println("b = " + b); // This compiles OK
}
};
}
}

Surprising access to fields with Java anonymous class

Despite the fact that I'm using System.out.println(a) rather than System.out.println(AnonTest.this.a) the code works and prints the correct result. How can this be?

Since the reference to a is unambiguous in your context, the two expressions reference the same field.

Generally, AnonTest.this is required in a very specific context - when your method needs to access AnonTest object itself, rather than accessing one of its members. In case of your program, this is unnecessary: the compiler resolves the expression a to the object AnonTest.this.a, and passes it to System.out.println.

How am I accessing my main class from an anonymous class?

In the case of the anonymous inner class this is the anonymous class itself. To access the outer class this from the anonymous one you need to do OuterClassName.this.

However an inner class is allowed to access variables and methods from the outer class. Whether the inner class is anonymous or not makes no difference what-so-ever.

See:

I thought inner classes could access the outer class variables/methods?

Java nested inner class access outer class variables

This is one of the most important differences between static and non-static inner classes.

You only need the class name if (for example) you have a method with the same name in both classes so it call tell which one you mean. That's what is happening with this, both the inner and outer class have a this - so it defaults to the inner one unless you say otherwise.

Access method of outer anonymous class from inner anonymous class

Since Java 8 the solution is pretty easy. Just store the method reference in a variable.

ReturnsANumber v = new ReturnsANumber() {
int theNumber() {
return 119;
}

public int getIt() {

Supplier<Integer> supplier = this::theNumber;

ReturnsANumber w = new ReturnsANumber() {
int theNumber() {
return 1;
}

public int getIt() {
return supplier.get();
}
};

return w.getIt();
}
};

Storing outer object could also do the trick. But for inherited methods only:

interface ReturnsANumber {
int theNumber();
int getIt();
}

public int getIt() {
ReturnsANumber outer = this;

ReturnsANumber w = new ReturnsANumber() {
public int theNumber() {
return 1;
}

public int getIt() {
return outer.theNumber();
}
};

return w.getIt();
}

You can store the method reference or the outer object as a field also.

Update

@Holger proposed another workaround. You can pass your outer object to a lambda:

ReturnsANumber v = new ReturnsANumber() {
...
@Override
public int getIt() {
ReturnsANumber w = Optional.of(this).map(outer ->
new ReturnsANumber() {
int theNumber() {
return 1;
}
public int getIt() {
return outer.theNumber();
}
}).get();
return w.getIt();
}
};

How to access this reference of anonymous outer class in java

You cannot access an instance of anonymous class directly from inner class or another anonymous class inside it, since the anonymous class doesn't have a name. However, you can get a reference to the outer class via a method:

new Outer()
{
public Outer getOuter()
{
return this;
}

public void outerMethod()
{
new Inner()
{
public void innerMethod()
{
getOuter().hashCode();
}
};
}
};

Can I access new methods in anonymous inner class with some syntax?

Once the anonymous class instance has been implicitly cast into the named type it can't be cast back because there is no name for the anonymous type. You can access the additional members of the anonymous inner class through this within the class, in the expression immediate after the expression and the type can be inferred and returned through a method call.

Object obj = new Object() {
void fn() {
System.err.println("fn");
}
@Override public String toString() {
fn();
return "";
}
};
obj.toString();

new Object() {
void fn() {
System.err.println("fn");
}
}.fn();

identity(new Object() {
void fn() {
System.err.println("fn");
}
}).fn();
...
private static <T> T identity(T value) {
return value;
}

Accessing inner anonymous class members

Anonymous inner classes have a type but no name.

You can access fields not defined by the named supertype. However once assigned to a named type variable, the interface is lost.

Obviously, you can access the fields from within the inner class itself. One way of adding code is through an instance initialiser:

final AtomicInteger y = new AtomicInteger();
new Runnable() {
int x;
{
x = 5;
doRun(this);
y.set(x);
}
public void run() {
... blah ...
}
};

The value returned by the anonymous inner class expression has the anonymous type, so you have one chance to use it outside of the class itself:

final int y = new Runnable() {
int x;
{
x = 5;
doRun(this);
}
public void run() {
... blah ...
}
}.x;

You can also pass it through a method declared similar to:

<T extends Runnable> T doRun(T runnable);

Access outer anonymous class from inner anonymous class

Unfortunately, you will have to give a name to the outer anonymous class:

public class Test{

public static void main(String args []){

class Foo extends JTable {

@Override
public void changeSelection(
final int row, final int column,
final boolean toggle, final boolean extend) {

SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Foo.super.changeSelection(row, column, toggle, extend);
//more code here
}
});
}
};

JTable table = new Foo();

}//end main

}//end test


Related Topics



Leave a reply



Submit