It is technically possible:
public class HasInner {
public static interface Foo {}
private static <T> T release(T instance, Object ref) {
try {
Class<?> type = instance.getClass();
for (Field field : type.getFields()) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
if (field.get(instance) == ref) {
field.set(instance, null);
}
}
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
return instance;
}
public Foo makeFoo() {
return release(new Foo() {}, this);
}
public static void main(String[] args) {
new HasInner().makeFoo();
}
}
The javap inspection of the anonymous class:
Compiled from "HasInner.java"
final class HasInner$1 extends java.lang.Object implements HasInner$
Foo{
final HasInner this$0;
HasInner$1(HasInner);
}
The implementation does not rely on the field name being this$0
as I suspect this is a compiler implementation detail.
Potential problem areas:
- A security manager may forbid the reflection code.
- I don't think the Java platform defines exactly how the inner type refers to the outer. That is, it is a compiler implementation detail and it would be legal, if stupid, to have an intermediary wrapper in the field - in the presence of other fields, disambiguating the reference may be impossible.
In short, I would never do this.
If this is a concern, use a private static inner class:
public class A {
private static class BImpl implements B {
@Override public void method() {
}
}
private final B b = new BImpl();
public B getB() { return b; }
}