在Java中,当我不在内部类时如何访问外部类?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/763543/
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-11 19:11:24  来源:igfitidea点击:

In Java, how do I access the outer class when I'm not in the inner class?

javasyntaxnested

提问by Kip

If I have an instance of an inner class, how can I access the outer class from code that is not in the inner class? I know that within the inner class, I can use Outer.thisto get the outer class, but I can't find any external way of getting this.

如果我有一个内部类的实例,如何从不在内部类中的代码访问外部?我知道在内部类中,我可以使用Outer.this来获取外部类,但是我找不到任何外部方式来获取它。

For example:

例如:

public class Outer {
  public static void foo(Inner inner) {
    //Question: How could I write the following line without
    //  having to create the getOuter() method?
    System.out.println("The outer class is: " + inner.getOuter());
  }
  public class Inner {
    public Outer getOuter() { return Outer.this; }
  }
}

采纳答案by Esko Luontola

The bytecode of the Outer$Innerclass will contain a package-scoped field named this$0of type Outer. That's how non-static inner classes are implemented in Java, because at bytecode level there is no concept of an inner class.

Outer$Inner该类的字节码将包含一个名为this$0type的包范围字段Outer。这就是非静态内部类在 Java 中的实现方式,因为在字节码级别没有内部类的概念。

You should be able to read that field using reflection, if you really want to. I have never had any need to do it, so it would be best for you to change the design so that it's not needed.

如果您真的愿意,您应该能够使用反射读取该字段。我从来没有必要这样做,所以你最好改变设计,这样就不需要了。

Here is how your example code would look like when using reflection. Man, that's ugly. ;)

以下是您的示例代码在使用反射时的样子。人,真丑。;)

public class Outer {
    public static void foo(Inner inner) {
        try {
            Field this
public static class Inner { // static now
    private final Outer parent;

    public Inner(Outer parent) { this.parent = parent; }

    public Outer get Outer() { return parent; }
}
= inner.getClass().getDeclaredField("this
public class Outer{ 
   public class Inner {
   }
}

public class UsesInner{
 Collection<Outer.Inner> c = new ArrayList<Outer.Inner>();
}
"); Outer outer = (Outer) this
public interface InnerClass<Outer> {
    Outer getOuter();
}
.get(inner); System.out.println("The outer class is: " + outer); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } public class Inner { } public void callFoo() { // The constructor of Inner must be called in // non-static context, inside Outer. foo(new Inner()); } public static void main(String[] args) { new Outer().callFoo(); } }

回答by Michael Borgwardt

There is no way, by design. If you need to access the outer class through an instance of the inner one, then your design is backwards: the point of inner classes is generally to be used only within the outer class, or through an interface.

没有办法,按设计。如果你需要通过内部类的实例访问外部类,那么你的设计是倒退的:内部类的点一般只在外部类中使用,或者通过接口。

回答by starblue

What's wrong with adding a getter when you need to access the outer class? That way you can control whether access is allowed or not.

需要访问外部类时添加getter有什么问题?这样您就可以控制是否允许访问。

回答by Outlaw Programmer

Can't you just do something like this:

你不能做这样的事情:

class MyInnerClass implements InnerClass<Outer> {
    Outer getOuter() {
        return Outer.this;
    }
    // remaining implementation details
}

回答by Steve B.

If you've got a (non-static) inner class, then you're by definition working with something that only functions inside the enclosing context of the outer class. So to get a handle to the inner class, you'd already have to have retrieved it through the outer instance. So the only way I can see to get to the point where you'd need an accessor like that is to have grabbed the inner through the outer ref and then lost or discarded the outer instance reference.

如果您有一个(非静态的)内部类,那么根据定义,您将使用仅在外部类的封闭上下文中起作用的东西。因此,要获得内部类的句柄,您必须已经通过外部实例检索它。因此,我认为要达到您需要这样的访问器的程度的唯一方法是通过外部引用获取内部引用,然后丢失或丢弃外部实例引用。

For example:

例如:

new InterfaceOrAbstractClass<Outer>() {
    Outer getOuter() { // super inefficient but this is the only way !
        return (Outer)getClass().getDeclaredField("this
class Outer {
  class Inner {
    Outer outer = Outer.this;
  }
}
"); } /* other methods */ }

Now the only way you can populate c is by creating Outer() instances. I'd be curious to see a useful purpose for something like this.

现在填充 c 的唯一方法是创建 Outer() 实例。我很想知道这样的事情的有用目的。

回答by Rich MacDonald

Here is one reason you may want this behavior: You have the inner classinstance and need to access a method defined in the outer classusing reflection.

以下是您可能想要这种行为的一个原因:您拥有内部class实例并且需要class使用反射访问在外部定义的方法。

For the record, inner.getClass().getDeclaredField("this$0")works. Since the field is private, you also need to call field.setAccessible(true).

为了记录,inner.getClass().getDeclaredField("this$0")作品。既然是字段private,你还需要调用field.setAccessible(true)

回答by Christophe Bouchon

This, in fact, is a very good question if, for example, you need to be able to check if two distinct instances of an Innnerclass share the same instance of Outerclass (== or equals depending on the context).

事实上,这是一个很好的问题,例如,如果您需要能够检查一个Innner类的两个不同实例是否共享同一个类实例Outer(== 或等于,取决于上下文)。

I'd suggest to make a general purpose interface (not absolutely required for named inner classes but can be "instancedof"/casted to):

我建议创建一个通用接口(命名内部类不是绝对必需的,但可以“实例化”/强制转换为):

##代码##

that can be applied to any named inner class.

可以应用于任何命名的内部类。

Then you do something like:

然后你做这样的事情:

##代码##

and this way you can access outer class from any inner class implementing InnerClass<Outer>interface (and check it actually implements it).

这样你就可以从任何实现InnerClass<Outer>接口的内部类访问外部类(并检查它是否实际实现了它)。

If your inner class is anonymous, you can only do (thanks to Rich MacDonald for its sample):

如果您的内部类是匿名的,您只能这样做(感谢 Rich MacDonald 的示例):

##代码##

but InterfaceOrAbstractClassmustimplements InnerClass<Outer>to be able to access getOuter()outside of the anonymous class body!

InterfaceOrAbstractClass必须实现InnerClass<Outer>才能getOuter()在匿名类主体之外访问!

It would be so much easier if javac automatically implemented some kind of InnerClass<Outer>interface on ALL inner classes, and it could do that super efficiently even on anonymous classes (no sluggish introspection processing)!

如果 javac 自动InnerClass<Outer>在所有内部类上实现某种接口会容易得多,并且即使在匿名类上也可以非常高效地做到这一点(没有缓慢的内省处理)!

回答by Igor

Simply write this

简单写下这个

##代码##