简体   繁体   English

从内部类对象获取外部类对象

[英]Getting hold of the outer class object from the inner class object

I have the following code.我有以下代码。 I want to get hold of the outer class object using which I created the inner class object inner .我想获取外部类对象,我使用它创建了内部类对象inner How can I do it?我该怎么做?

public class OuterClass {

    public class InnerClass {
        private String name = "Peakit";
    }

    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        InnerClass inner = outer.new InnerClass();
       // How to get the same outer object which created the inner object back?
        OuterClass anotherOuter = ?? ;

        if(anotherOuter == outer) {
             System.out.println("Was able to reach out to the outer object via inner !!");
        } else {
             System.out.println("No luck :-( ");
        }
    }
}

EDIT: Well, some of you guys suggested of modifying the inner class by adding a method:编辑:嗯,你们中的一些人建议通过添加一个方法来修改内部类:

public OuterClass outer() {
   return OuterClass.this;
}

But what if I don't have control to modify the inner class, then (just to confirm) do we have some other way of getting the corresponding outer class object from the inner class object?但是如果我没有控制修改内部类,那么(只是为了确认)我们是否有其他方法可以从内部类对象中获取相应的外部类对象?

Within the inner class itself, you can use OuterClass.this .在内部类本身中,您可以使用OuterClass.this This expression, which allows to refer to any lexically enclosing instance, is described in the JLS as Qualified this .这个表达式允许引用任何词法封闭实例,在 JLS 中被描述为Qualified this

I don't think there's a way to get the instance from outside the code of the inner class though.认为没有办法从内部类的代码之外获取实例。 Of course, you can always introduce your own property:当然,你可以随时介绍自己的财产:

public OuterClass getOuter() {
    return OuterClass.this;
}

EDIT: By experimentation, it looks like the field holding the reference to the outer class has package level access - at least with the JDK I'm using.编辑:通过实验,看起来保存对外部类的引用的字段具有包级别访问权限 - 至少对于我正在使用的 JDK。

EDIT: The name used ( this$0 ) is actually valid in Java, although the JLS discourages its use:编辑:使用的名称( this$0Java实际上是有效的,虽然JLS阻碍了它的用法:

The $ character should be used only in mechanically generated source code or, rarely, to access pre-existing names on legacy systems. $字符应该只在机械生成的源代码中使用,或者很少用于访问遗留系统上预先存在的名称。

OuterClass.this引用外部类。

You could (but you shouldn't) use reflection for the job:你可以(但你不应该)在工作中使用反射:

import java.lang.reflect.Field;

public class Outer {
    public class Inner {
    }

    public static void main(String[] args) throws Exception {

        // Create the inner instance
        Inner inner = new Outer().new Inner();

        // Get the implicit reference from the inner to the outer instance
        // ... make it accessible, as it has default visibility
        Field field = Inner.class.getDeclaredField("this$0");
        field.setAccessible(true);

        // Dereference and cast it
        Outer outer = (Outer) field.get(inner);
        System.out.println(outer);
    }
}

Of course, the name of the implicit reference is utterly unreliable, so as I said, you shouldn't :-)当然,隐式引用的名称完全不可靠,所以正如我所说,你不应该:-)

The more general answer to this question involves shadowed variables and how they are accessed.对这个问题的更一般的回答涉及影子变量及其访问方式。

In the following example (from Oracle), the variable x in main() is shadowing Test.x :在以下示例中(来自 Oracle), main() 中的变量x正在隐藏Test.x

class Test {
    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();
    }
}

Running this program will print:运行这个程序将打印:

x=0, Test.this.x=1

More at: http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6更多信息: http : //docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6

Here's the example:这是示例:

// 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";
   }
}

if you don't have control to modify the inner class, the refection may help you (but not recommend).如果您无法控制修改内部类,反射可能会对您有所帮助(但不推荐)。 this$0 is reference in Inner class which tells which instance of Outer class was used to create current instance of Inner class. this$0 是内部类中的引用,它告诉我们使用外部类的哪个实例来创建内部类的当前实例。

I have the following code.我有以下代码。 I want to get hold of the outer class object using which I created the inner class object inner .我想掌握使用外部类对象创建内部类对象inner How can I do it?我该怎么做?

public class OuterClass {

    public class InnerClass {
        private String name = "Peakit";
    }

    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        InnerClass inner = outer.new InnerClass();
       // How to get the same outer object which created the inner object back?
        OuterClass anotherOuter = ?? ;

        if(anotherOuter == outer) {
             System.out.println("Was able to reach out to the outer object via inner !!");
        } else {
             System.out.println("No luck :-( ");
        }
    }
}

EDIT: Well, some of you guys suggested of modifying the inner class by adding a method:编辑:嗯,你们中的一些人建议通过添加方法来修改内部类:

public OuterClass outer() {
   return OuterClass.this;
}

But what if I don't have control to modify the inner class, then (just to confirm) do we have some other way of getting the corresponding outer class object from the inner class object?但是,如果我没有控制权来修改内部类,那(只是确认一下),我们还有其他方法可以从内部类对象中获取相应的外部类对象吗?

/**
 * 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);
}

Of course, the name of the implicit reference is unreliable, so you shouldn't use reflection for the job.当然,隐式引用的名称是不可靠的,因此您不应该对作业使用反射。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM