java中内部类获取外部类对象_关于java:从内部类对象获取外部类对象

我有以下代码。我想了解创建内部类对象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 :-(");

}

}

}

编辑:好吧,你们中的一些人建议通过添加一个方法来修改内部类:

public OuterClass outer() {

return OuterClass.this;

}

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

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

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

public OuterClass getOuter() {

return OuterClass.this;

}

编辑:通过实验,保存对外部类的引用的字段似乎具有包级访问权限——至少对于我使用的JDK是这样的。

编辑:使用的名称(EDCOX1(2))在Java中实际上是有效的,尽管JLS阻止了它的使用:

The $ character should be used only in

mechanically generated source code or,

rarely, to access pre-existing names on

legacy systems.

谢谢乔恩!但是如果我没有修改内部类的控制权(检查我的编辑)。

@匹克伊特:据我所知,除非你用反省,否则你就走运了。这感觉像是对封装的侵犯——如果内部类不想告诉您它的外部实例是什么,您应该尊重它,并尝试设计出不需要它的类。

这在Java 8中仍然有效吗?

OuterClass.this引用了外部类。

但只有在外环的源头内。我不认为这就是手术室想要的。

你可以(但不应该)用反省来做这份工作:

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

}

}

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

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

在下面的示例中(来自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

更多信息,请访问: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";

}

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值