可见性如何适用于Java嵌套类?

时间:2015-02-01 21:07:05

标签: java visibility

我试图了解分配给嵌套类的可见性,除了我的IDE对我大吼大叫之外我还要做什么。这可能会变得任意复杂,所以我需要理解一般规则。

public class A {
    private static class B {
        public int foo; // accessible in A?
        private int bar; // accessible in A?
        public static class C { // accessible in A? everywhere?
        }
        private static class D { // accessible in A?
        }
    }
}

据我了解,修饰符似乎在"文件中解析了#34;级别,而不是封装类的级别。一旦有一件事是私人的,其中的任何东西都是私人的。

这个或技术解释的实际机制是什么?这是在某处记录的还是我只需要阅读JLS?

2 个答案:

答案 0 :(得分:9)

我见过的最佳访问可见性摘要之一是Java Tutorials > Controlling access to members of a class,但它隐藏了一些关键细节。我认为你问的问题在SE 7的JLS第6.6.1节得到了回答:"Determining Accessibility"

  

如果......公共......否则,如果......受保护......否则,如果...包访问...

     

否则,成员或构造函数被声明为private,当且仅当它出现在包含成员或构造函数声明的顶级类(第7.6节)的主体内时才允许访问

如果你仔细阅读:

  1. 任何访问
  2. 在顶级课程的主体内
  3. 到另一个private(不是包私有 - 那是不同的)成员
  4. 无论嵌套的深度如何
  5. 允许
  6. 因此:任何深度的私有嵌套类中的任何成员都可以在顶层类的正文中的任何位置访问(包括在其他嵌套的兄弟类中)。但是,私有嵌套类及其中的任何成员对其他顶级类是不可见的。

    例如:

    public class A {
        private static class B {
            public int foo; // accessible in A and P
            private int bar; // accessible in A and P   
            public static void test(){
                P p = new P();
                p.foo = 1; p.bar = 1;
            }
        }
        private static class P {
            public int foo; // accessible in A and B
            private int bar; // accessible in A and B   
            public static void test(){
                B b = new B();
                b.foo = 1; b.bar = 1;
            }
        }
        public static void test(){
            B b = new B();
            b.foo = 1; b.bar = 1;
            P p = new P();
            p.foo = 1; p.bar = 1;       
        }
    }
    

    注意:但这不是“文件级别”。在该文件中声明另一个顶级类(不能是public - 每个文件只允许其中一个)并且它看不到那些相同的嵌套private成员。

    class X {
        public static void test() {
            // all of these statements fail ...
            A.B b = new A.B();
            b.foo = 1; b.bar = 1; 
            b.test();
            A.P p = new A.P();
            p.foo = 1; p.bar = 1;  
            p.test();
        }
    
    }
    

答案 1 :(得分:3)

辅助功能与访问源相关。第一

  

否则,会员或构造函数被声明为private并进行访问   当且仅当它出现在顶层的主体内时才被允许   包含成员或的声明的类(第7.6节)   构造

因此,A中声明的所有成员或A中的类中嵌套的所有成员都可以在A中访问。

如果您不在A范围内,则private A成员无法访问。这意味着B无法访问。由于foobarCDB的成员,因此您需要B才能访问它们。但由于B无法访问,因此您无法访问它们。

public class Unrelated {
   {
       B b; // nope
       A.B b; // nope
       A.B.C c; // nope 
   }
}

这些规则或多或少都是在JLS的this section中定义的。