Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从内部类对象获取外部类对象_Java_Inner Classes - Fatal编程技术网

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

Java 从内部类对象获取外部类对象,java,inner-classes,Java,Inner Classes,我有以下代码。我想获得外部类对象,我使用它创建了内部类对象internal。我怎么做 public class OuterClass { public class InnerClass { private String name = "Peakit"; } public static void main(String[] args) { OuterClass outer = new OuterClass(); Inner

我有以下代码。我想获得外部类对象,我使用它创建了内部类对象
internal
。我怎么做

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 :-( ");
        }
    }
}
编辑:好吧,你们中的一些人建议通过添加一个方法来修改内部类:

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

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

在内部类本身中,您可以使用
外部类。此表达式允许引用任何词汇封闭实例,在JLS中描述为

不过,我认为没有办法从内部类的代码之外获取实例。当然,您可以随时介绍自己的物业:

public OuterClass getOuter() {
    return OuterClass.this;
}
编辑:通过实验,看起来保存外部类引用的字段具有包级别的访问权限——至少在我使用的JDK中是这样

编辑:所使用的名称(
此$0
)在Java中实际上是有效的,但不鼓励使用:

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


OuterClass。此
引用外部类。

您可以(但不应该)对作业使用反射:

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);
    }
}
当然,隐式引用的名称是完全不可靠的,所以正如我所说的,您不应该:-)

下面是一个示例:

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

这个问题的更一般的答案涉及隐藏变量以及如何访问它们

在下面的示例(来自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();
    }
}
运行此程序将打印:

x=0, Test.this.x=1

更多信息请访问:

如果您没有修改内部类的控件,则refection可能会帮助您(但不推荐)。这个$0是内部类中的引用,它告诉我们外部类的哪个实例被用来创建内部类的当前实例

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

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

谢谢Jon!但是如果我无法控制修改内部类(请检查我的编辑)。@peakit:那么就我所知,除非你使用反射,否则你就不走运了。这感觉像是违反了封装,但实际上-如果内部类不想告诉你它的外部实例是什么,你应该尊重这一点,并尝试设计成你不需要它。这在Java 8中仍然有效吗?@misty是的,是的。但只在外部类的源代码中/内部有效。我不认为这是OP想要的。“静态内部”在术语上是矛盾的。不确定该示例是否能最好地证明这一点,因为“Test.this.x”与“Test.x”相同,因为它是静态的,并不真正属于封闭类对象。我认为如果代码在类Test和Test.x的构造函数中而不是静态的话,这将是一个更好的例子。