有以下代码。 我想知道用于创建内部类对象inner的外部类对象。 我该怎么办?
公共类外类{
公共类inner类{
私有字符串name=' peak it ';
}
publicstaticvoidmain (字符串[ ] args ) {
OuterClass outer=new OuterClass (;
inner class inner=outer.new inner class (;
//howtogetthesameouterobjectwhichcreatedtheinnerobjectback?
OuterClass anotherOuter=?
if (通告程序输出器==输出器) {
system.out.println (wasabletoreachouttotheouterobjectviainner! ' );
} else {
system.out.println (' no luck :-();
}
}
}
编辑:那么,你们中的一些人建议添加方法来修改内部类:
公共输出类输出器
return OuterClass.this;
}
号
但是,如果没有更改内部类的控制权,还有其他方法(只需确认)从内部类对象中获取相应的外部类对象吗?
内部类本身可以使用OuterClass.this。 在此表达式中,可以引用在JLS中描述为有限this的任何词汇封闭实例。
但是,我认为没有办法从内部类的代码以外获取实例。 当然,你可以随时介绍自己的财产。
公共输出类get outer
return OuterClass.this;
}
编辑:根据实验,用于存储对外部类的引用的字段似乎具有软件包级权限——。 至少在我使用的JDK中是这样。
编辑:使用的名称(EDCOX1(2)2) )在Java中实际上有效,尽管JLS阻止了使用。
the $ charactershouldbeusedonlyin
机械工程师协会,
rarely,to access pre-existing names on
遗留系统。
号
谢谢你广阔的白云! 但是如果我没有修改内部类的控制权(检查我的编辑。
@xldsh :据我所知,只要你不用反省,你就很幸运。 我觉得这好像是对包装的侵犯。 如果——内部类不想告诉您外部实例是什么,请尊重它,然后尝试设计不需要它的类。
这在Java 8中也有效吗?
OuterClass.this引用了外部类。
但它只存在于外环的源头中。 我不认为这就是我想要的手术室。
我可以带着反省做这项工作。 但是,不应该。
import java.lang.reflect.Field;
公共类输出器{
公共类inner {
}
publicstaticvoidmain (字符串[ ] args ) throws Exception { )。
//创建the inner instance
Inner inner=new Outer ().new Inner );
//gettheimplicitreferencefromtheinnertotheouterinstance
//makeitaccessible,as it has default visibility
field field=inner.class.getdeclaredfield (' this $0);
field.set accessible (真;
//de参考和铸造it
outerouter=(outer ) field.get ) inner;
system.out.println(outer );
}
}
号
当然,隐含引用的名称完全不可靠,就像我说的,你不应该:—)
这个问题的更常见答案是隐藏变量以及访问它们的方法。
在以下示例中,main ()的变量x从Oracle中隐藏了test.x。
类测试{
>static int x = 1;public static void main(String[] args) {
InnerClass innerClassInstance = new InnerClass()
{
public void printX()
{
System.out.print("x=" + x);
System.out.println(", Test.this.x=" + Test.this.x);
}
}
innerClassInstance.printX();
}
public abstract static class InnerClass
{
int x = 0;
public InnerClass() { }
public abstract void printX();
}
}
运行此程序将打印:
x=0, Test.this.x=1
。
更多信息,请访问:http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html jls-6.6
/**
* Not applicable to Static Inner Class (nested class)
*/
public static Object getDeclaringTopLevelClassObject(Object object) {
if (object == null) {
return null;
}
Class cls = object.getClass();
if (cls == null) {
return object;
}
Class outerCls = cls.getEnclosingClass();
if (outerCls == null) {
// this is top-level class
return object;
}
// get outer class object
Object outerObj = null;
try {
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
if (field != null && field.getType() == outerCls
&& field.getName() != null && field.getName().startsWith("this$")) {
field.setAccessible(true);
outerObj = field.get(object);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return getDeclaringTopLevelClassObject(outerObj);
}
当然,隐式引用的名称是不可靠的,因此您不应该为该作业使用反射。
public class Outer {
public Inner getInner(){
return new Inner(this,this.getClass());
}
class Inner {
public Inner(Outer outer, Class extends Outer> aClass) {
System.out.println(outer);
System.out.println(aClass.getName());
System.out.println();
}
}
public static void main(String[] args) {
new Outer().getInner();
}
}
。
如果您没有修改内部类的控件,那么refection可能会帮助您(但不推荐)。这个$0是内部类中的引用,它告诉外部类的哪个实例被用来创建内部类的当前实例。
我就是这样做的:
public class CherryTree {
public class Cherry {
public final CherryTree cherryTree = CherryTree.this;
// [...]
}
// [...]
}
。
当然,您需要能够修改内部类,并且每个获得内部类对象的人现在都可以访问外部类对象。就我而言,一切都很好。
示例如下:
// Test
public void foo() {
C c = new C();
A s;
s = ((A.B)c).get();
System.out.println(s.getR());
}
// classes
class C {}
class A {
public class B extends C{
A get() {return A.this;}
}
public String getR() {
return"This is string";
}
}