Kip*_*Kip 32 java syntax nested
如果我有一个内部类的实例,我如何从不在内部类中的代码访问外部类?我知道在内部类中,我可以Outer.this
用来获取外部类,但我找不到任何外部方法来获取它.
例如:
public class Outer {
public static void foo(Inner inner) {
//Question: How could I write the following line without
// having to create the getOuter() method?
System.out.println("The outer class is: " + inner.getOuter());
}
public class Inner {
public Outer getOuter() { return Outer.this; }
}
}
Run Code Online (Sandbox Code Playgroud)
Esk*_*ola 32
Outer$Inner
该类的字节码将包含一个名为this$0
type 的包范围字段Outer
.这就是用Java实现非静态内部类的方式,因为在字节码级别没有内部类的概念.
如果你真的想,你应该能够使用反射读取该字段.我从来没有任何需要这样做,所以你最好改变设计,这样就不需要了.
以下是使用反射时示例代码的外观.伙计,那很难看.;)
public class Outer {
public static void foo(Inner inner) {
try {
Field this$0 = inner.getClass().getDeclaredField("this$0");
Outer outer = (Outer) this$0.get(inner);
System.out.println("The outer class is: " + outer);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public class Inner {
}
public void callFoo() {
// The constructor of Inner must be called in
// non-static context, inside Outer.
foo(new Inner());
}
public static void main(String[] args) {
new Outer().callFoo();
}
}
Run Code Online (Sandbox Code Playgroud)
Mic*_*rdt 14
没有办法,按设计.如果需要通过内部类的实例访问外部类,那么您的设计是向后的:内部类的点通常仅在外部类中使用,或者通过接口使用.
小智 6
事实上,这是一个非常好的问题,例如,如果您需要能够检查Outer
类的两个不同实例是否共享同一个类实例InnerClass<Outer>
(==或等于取决于上下文).
我建议创建一个通用接口(对于命名的内部类不是绝对必需的,但可以是"instancedof"/ casted to):
public interface InnerClass<Outer> {
Outer getOuter();
}
Run Code Online (Sandbox Code Playgroud)
可以应用于任何命名的内部类.
然后你做的事情如下:
class MyInnerClass implements InnerClass<Outer> {
Outer getOuter() {
return Outer.this;
}
// remaining implementation details
}
Run Code Online (Sandbox Code Playgroud)
这样你就可以从任何实现InterfaceOrAbstractClass
接口的内部类访问外部类(并检查它实际实现了它).
如果你的内部类是匿名的,你只能这样做(感谢Rich MacDonald的样本):
new InterfaceOrAbstractClass<Outer>() {
Outer getOuter() { // super inefficient but this is the only way !
return (Outer)getClass().getDeclaredField("this$0");
}
/* other methods */
}
Run Code Online (Sandbox Code Playgroud)
但InnerClass<Outer>
必须实现getOuter()
能够访问InnerClass<Outer>
匿名类体外!
如果javac自动Outer
在所有内部类上实现某种接口,那么它就会变得容易得多,即使在匿名类上也可以非常有效地执行(没有缓慢的内省处理)!