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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1816458/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 22:55:44  来源:igfitidea点击:

Getting hold of the outer class object from the inner class object

javainner-classes

提问by peakit

I have the following code. I want to get hold of the outer class object using which I created the inner class object inner. How can I do it?

我有以下代码。我想使用我创建内部类对象的外部类对象inner。我该怎么做?

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?

但是如果我无法控制修改内部类,那么(只是为了确认)我们是否有其他方法可以从内部类对象中获取相应的外部类对象?

采纳答案by Jon Skeet

Within the inner class itself, you can use OuterClass.this. This expression, which allows to refer to any lexically enclosing instance, is described in the JLS as Qualified this.

在内部类本身中,您可以使用OuterClass.this. 这个表达式允许引用任何词法封闭实例,在 JLS 中被描述为Qualifiedthis

I don't thinkthere'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) isactually valid in Java, although the JLSdiscourages its use:

编辑:使用(这个名字this$0在Java中确实有效,虽然JLS阻碍了它的用法:

The $character should be used only in mechanically generated source code or, rarely, to access pre-existing names on legacy systems.

$字符应仅用于机械生成的源代码,或者很少用于访问遗留系统上预先存在的名称。

回答by bmargulies

OuterClass.thisreferences the outer class.

OuterClass.this引用外部类。

回答by Lukas Eder

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

当然,隐式引用的名称完全不可靠,所以正如我所说,你不应该:-)

回答by Ashish Rawat

Here's the example:

这是示例:

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

回答by Gladclef

The more general answer to this question involves shadowed variables and how they are accessed.

对这个问题的更一般的回答涉及影子变量及其访问方式。

In the following example (from Oracle), the variable xin main()is shadowing Test.x:

在下面的例子(从Oracle),变量X主()被遮蔽Test.x

x=0, Test.this.x=1

Running this program will print:

运行这个程序将打印:

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

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

回答by u6577041

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 是内部类中的引用,它告诉我们使用外部类的哪个实例来创建内部类的当前实例。

回答by kyakya

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

回答by Vali Zhao

##代码##

Of course, the name of the implicit reference is unreliable, so you shouldn't use reflection for the job.

当然,隐式引用的名称是不可靠的,因此您不应该对作业使用反射。