【问题标题】:Visibility of inner class explanation内部类解释的可见性
【发布时间】:2020-08-29 02:59:17
【问题描述】:

我想比较两件事。我们知道:

  1. 内部类可以访问外部类的每个成员。
  2. 外部类无法访问内部类的成员。除非您创建内部类的对象。

我的问题是为什么会这样?为什么外部类也不能访问内部类的成员?这是一个很清楚的例子:

public class OuterClass {
    String stringOuter;

    void m1(){
       //can call just stringOuter
       InnerClass i = new InnerClass();
       i.stringInner; //can call stringInner when you make object
    }

    class InnerClass{
        String stringInner;

        void m2(){
            //can call stringOuter and stringInner
            //doesn't need object from OuterClass
        }
    }
}

【问题讨论】:

    标签: java scope inner-classes


    【解决方案1】:

    首先,您的stringOuterstringInner字段,而不是方法。因此,您不能“调用”它们,并且您的 i.stringInner; 示例仍然无法编译,因为它不是语句。

    为了使示例有效,我们可以将字段的值分配给另一个变量。

    public class OuterClass {
        String stringOuter;
    
        void m1() {
           InnerClass i = new InnerClass();
           String s = i.stringInner;
        }
    
        class InnerClass {
            String stringInner;
    
            void m2() {
                String s = stringOuter;
            }
        }
    }
    

    void m2() { String s = stringOuter; } 起作用的原因在于,与具有 static 修饰符的嵌套类相比,内部类始终具有外部类的关联实例。

    您的示例方法m2() 等效于

    void m2() {
        OuterClass o = OuterClass.this;
        String s = o.stringOuter;
    }
    

    在您的示例中,对外部类实例的引用的初始化是隐式的,它仅适用于 OuterClass 的实例在范围内的上下文。所以当你把m1()方法改成

    static void m1() {
       InnerClass i = new InnerClass(); // compiler error
       String s = i.stringInner;
    }
    

    它不再起作用了,因为没有 OuterClass 的实例。您可以提供一个显式实例:

    static void m1() {
        OuterClass outer = new OuterClass();
        InnerClass i = outer.new InnerClass(); // uses outer
        String s = i.stringInner;
    }
    

    但这是 Java 编程语言中很少使用的特性。

    如前所述,如果将内部类更改为嵌套类,则可以在没有外部类实例的情况下对其进行实例化,但如果不显式指定实例,也无法访问非静态成员:

    public class OuterClass {
        String stringOuter;
    
        static void m1() {
            InnerClass i = new InnerClass(); // no problem
            String s = i.stringInner;
        }
    
        static class InnerClass {
            String stringInner;
    
            void m2() {
                String s1 = new OuterClass().stringOuter; // works
                String s = stringOuter; // does not work
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      OuterClass 可以根据类型(静态或非静态)访问 InnerClass 数据成员。对于非静态数据成员,允许通过对象进行访问,对于静态数据成员,允许通过类名进行访问(示例如下)。

      根据您的示例,InnerClass 具有非静态数据成员,它们只能通过对象访问。这就是您能够通过对象访问 stringInner 的原因。如果您要在 InnerClass 中声明一个静态数据成员,那么您可以通过 InnerClass.staticDataMember 直接访问它。

      每当我们创建一个类的对象时,它都会分配一个由所有非静态数据成员组成的内存。由于这些数据成员是该对象的一部分,因此我们可以通过 object.dataMember 语句访问这些​​数据成员。

      我希望它能澄清你的答案?

      【讨论】:

      • 是的,一切都清楚了。 Outer 将 Inner 视为与任何其他类相同。但是,Inner 类如何在不创建 Outer 类型的对象的情况下访问 Outer 中的所有内容呢?他们不应该“一样”工作吗?
      • 首先,您的内部类不是私有的,因此任何有权访问 OuterClass 的人都可以像 OuterClass.InnerClass 一样访问 InnerClass。当你创建一个外部类的实例时,你可以通过 outerClassObject.innerClassNonStaticObject 访问内部类的非静态数据成员。
      【解决方案3】:

      我想类声明只是模板,它也适用于内部类,除非您从内部类(模板)或任何其他您无法访问其成员的类中实例化一个对象。例外是静态成员,因为它们驻留在类区域中。

      【讨论】:

      • 没错,我的问题在于 Inner 可以直接访问所有内容。与 Outer 不同,这需要创建 Inner 的实例来访问实例成员或使用类名来访问静态成员。这是为什么? ://
      猜你喜欢
      • 2015-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 2013-07-26
      • 2022-12-01
      • 2017-02-20
      相关资源
      最近更新 更多