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 ofHello
and whose parent isChild
The confusion in the code is about the latter:
Hello$1
is a subclass ofChild
Hello$1
is an inner class ofHello
This means:
Hello$1
cannot access private fields fromChild
, as subclasses cannot access private elements of their super classesHello$1
can access private fields fromHello
, 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 thanSystem.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
How Can "This" of the Outer Class Be Accessed from an Inner Class
How Does System.Out.Print() Work
Java Native Method Source Code
Why Is Files.Lines (And Similar Streams) Not Automatically Closed
Cancelling a Long Running Regex Match
Detect If Java Application Was Run as a Windows Admin
Java How Expensive Is a Method Call
Stream Filter of 1 List Based on Another List
Java Converting Int to Hex and Back Again
What Do Curly Braces in Java Mean by Themselves
Problems with Local Variable Scope. How to Solve It