【问题标题】:Two questions on inner classes in Java (class A { class B { } })关于Java内部类的两个问题(class A { class B { } })
【发布时间】:2008-12-04 00:31:34
【问题描述】:

抱歉标题不好,但我想不出更好的标题。

我有一个 A 类和一个 B 类,它是 A 的子类,如下所示:

(它实际上有正确的名称吗?“子类”不是为继承保留的吗?)

class A {
    int i = 0;
    class B {
        int j = 1;
    }
}

class Test {
    public static void main() {
        A a = new A();
        B b = a.new B();
        A c = ??? b ??? // get "a" back
    }
}

从 B 可以访问 A 的每个属性,因此 a.i 和 b.i 都返回 0。现在,我想知道是否有可能从 b 中检索类型 A 的原始对象,因为 b 包含所有一个包含?简单的转换显然不能解决问题。

第二个:

class A {

    void print() {
        System.out.println("This is class A.");
    }

    class B {
        void print() {
            // <--- How to access print() of class A (like this.A.print() or smth)? 
            System.out.println("This is class B.");
        }
    }
}

你也可以为我提供一些关于这个主题的好资源,因为到目前为止我太笨了,找不到好的资源。

提前致谢。 :)

【问题讨论】:

  • 我相信正确的名字是内部类。
  • 我相信这是这个问题的重复(stackoverflow.com/questions/309737/…
  • 其实我总是又忘记了这个“classname.this”语法:)
  • A c = b.this$0; 有效吗?

标签: java class


【解决方案1】:

似乎没有办法从外部访问外部类。但你可以这样做:

class A {
    int i = 0;
    class B {
        final A outer = A.this;
        int j = 1;
    }
}

class Test {
    public static void main() {
        A a = new A();
        A.B b = a.new B();
        A c = b.outer // get "a" back
    }
}

ClassName.this 将是与内部类实例关联的外部类实例。

【讨论】:

  • 我认为 B b = ... 是错误的。如果不使用 A.A.B b = ... 会更好..
  • 为了安全起见,我会声明 final A outer = A.this;
  • 一个更优雅的解决方案是提供一个类似outer()的方法来返回A.this来保存添加一个字段。
  • 添加一个字段不仅会浪费空间,而且会产生循环依赖,这对于 GC 来说更难清理。
  • @Peter Lawrey:将 final A external = A.this 添加到内部类 B 无论如何都会隐式发生。约翰内斯只是简单地把它说清楚。检查没有最终 A 外部变量的反汇编 A$B.class:>javap A$B 编译自“A.java”类 maxim.A$B extends java.lang.Object{ int j;最终格言.A this$0;最大值.A$B(最大值.A); }
【解决方案2】:

您可以在内部类中使用ParentClass.this 语法访问它。

例如

public class Outter
{
    class Inner {
        public Outter getOutter()
        {
            return Outter.this;
        }
    }

    public Inner getInner(){
        return new Inner();
    }
}

class Runner{
    public static void main(String[] args){
        Outter out = new Outter(); 
        Outter.Inner inner = out.getInner();

        System.out.println(inner.getOutter().toString());
    }
}

【讨论】:

    【解决方案3】:

    [编辑:我的回答适合 C# 程序员,但我不能保证它适用于 Java。]

    B 是内部类,而不是 A 的子类。此外,B 不包含 A 的实例,因此您的代码按原样无法返回 A 的任何实例。

    您需要按如下方式重组您的类:

    class A
    {
        public class B
        {
           public A Parent;
           public B(A parent)
           {
              this.Parent = parent;
           }
        }
    }
    

    现在您的 B 类有一个字段“Parent”,它返回其父级。可以按如下方式使用这些类(这是C#语法,因为我不知道Java是否有不同的语法来实例化内部类):

    public static void Main(String[] args)
    {
        A parent = new A();
        A.B child = new A.B(child);
        A backToParent = child.Parent;
    }
    

    当然,以这种方式创建您的 B 类似乎有点滑稽:从技术上讲,您可以传入任何父级。使用返回 B 的方法重写您的 A 类可能会更好:

    class A
    {        
        public class B
        {
           public A Parent;
           public B(A parent)
           {
              this.Parent = parent;
           }
        }
    
        public B getChild()
        {
            return new B(this);
        }
    }
    
    public static void Main(String[] args)
    {
        A parent = new A();
        A.B child = A.getChild();
        A backToParent = child.Parent;
    }
    

    【讨论】:

    • 事实上,它确实包含 A 的一个实例。另请参阅:stackoverflow.com/questions/309737/… 但是,感谢您的回答。您描述的方式肯定是另一种解决方案。
    • 似乎“内部类”指的是与 Java 中不同的概念(大约是 Java 所称的“嵌套类”)。
    【解决方案4】:

    这似乎对我有用

    class A {
        int i = 0;
        class B {
            int j = 1;
        }
    }
    
    class Test {
        public static void main() {
            A a = new A();
            A.B b = a.new B();
            A c = (A)b.getClass().getDeclaredField("this$0").get(b);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-07-14
      • 1970-01-01
      • 2020-08-03
      • 2021-12-03
      • 2010-11-30
      • 1970-01-01
      • 1970-01-01
      • 2011-12-22
      • 1970-01-01
      相关资源
      最近更新 更多