技术上是可行的:
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();
}
}
匿名类的javap检查:
Compiled from "HasInner.java"
final class HasInner$1 extends java.lang.Object implements HasInner$
Foo{
final HasInner this$0;
HasInner$1(HasInner);
}
该实现不依赖于字段名称,this$0
因为我怀疑这是编译器实现细节。
潜在问题领域:
- 安全管理器可以禁止反射代码。
- 我认为Java 平台并没有准确定义内部类型如何引用外部。也就是说,它是一个编译器实现细节,如果愚蠢的话,在该字段中有一个中间包装器是合法的——在存在其他字段的情况下,消除引用的歧义可能是不可能的。
简而言之,我永远不会这样做。
如果这是一个问题,请使用私有静态内部类:
public class A {
private static class BImpl implements B {
@Override public void method() {
}
}
private final B b = new BImpl();
public B getB() { return b; }
}