Java 中,当生成一个内部类的对象时,此对象与制造它的外部类通过外部类的 .this 保持着联系,因此该内部类对象可以访问其外部类对象的所有成员,包括 private 成员。
而该内部类对象对于其他类的对象的访问,遵照常规的访问权限语法,这一点也没有什么特别支持。这里需要探讨的是,外部类以及其他类的对象可以如何访问到某个内部类对象,即内部类的可见性问题。
下面是一个示例程序 Out.java ,其中包含了 4 个不同访问权限的内部类( private,default,protected,public ),在每个内部类中,分别包含 4 个不同访问权限的成员与方法。在外部类 Out 中提供了得到内部类实例的方法。
Out.java

package com.zj.main;

 

public class Out {

    public PrivateIn getPrivateIn(){

       return new PrivateIn();

    }

   

    public DefaultIn getDefaultIn(){

       return new DefaultIn();

    }

   

    public ProtectedIn getProtectedIn(){

       return new ProtectedIn();

    }

   

    public PublicIn getPublicIn(){

       return new PublicIn();

    }

   

    private class PrivateIn implements InMethod{

       private int private_arg ;

       int default_arg ;

       protected int protected_arg ;

       public int public_arg ;

      

       private void private_method(){};

       void default_method(){};

       protected void protected_method(){};

       public void public_method(){};

    }

   

    class DefaultIn implements InMethod{

       private int private_arg ;

       int default_arg ;

       protected int protected_arg ;

       public int public_arg ;

      

       private void private_method(){};

       void default_method(){};

       protected void protected_method(){};

       public void public_method(){};

    }

   

    protected class ProtectedIn implements InMethod{

       private int private_arg ;

       int default_arg ;

       protected int protected_arg ;

       public int public_arg ;

      

       private void private_method(){};

       void default_method(){};

       protected void protected_method(){};

       public void public_method(){};

    }

   

    public class PublicIn implements InMethod{

       private int private_arg ;

       int default_arg ;

       protected int protected_arg ;

       public int public_arg ;

      

       private void private_method(){};

       void default_method(){};

       protected void protected_method(){};

       public void public_method(){};

    }

 

    public static void main(String[] args){

       //create an outer object

       Out out= new Out();

      

       //create a private inner object by 'new'

       Out.PrivateIn privateIn=out. new PrivateIn();

       privateIn. private_arg =0;

       privateIn.private_method();

      

       // create a private inner object  by 'out's method'

       Out.PrivateIn privateIn2 = out.getPrivateIn();

       privateIn2. private_arg = 0;

       privateIn2.private_method();

    }

}

所有的 4 个内部类都实现了一个接口 InMethod ,该接口的作用在下文中会有讨论。下面先讨论内部类所在的外部类对其内部类对象的访问权限问题。
1. 外部类的访问

我们通过两种两种方式试图创建内部类的实例。
方式一 OuterClassName.InnerClassName inner=new Ouer().new Inner();

通过外部类对象 .new 的方式,可以得到 private inner class 的实例,并且可以访问它的 private 成员和 private 方法。自然 default protected public 的都可以访问。

 

方式二 通过外部类方法 get InnerInstance()

此种方法也可以访问所有内部类的所有成员和方法。
所以,一个内部类的对象对生成它的外部类对象是完全可见的,包括 private 内部类、 private 成员与 private 方法。
2. 同包其他类的访问

下面,在同一个包内创建一个 SamePackage.java 类,试图访问 Out 类的所有内部类。
SamePackage.java

package com.zj.main;

 

public class SamePackage {

    public static void main(String[] args) {

       // create an outer object

       Out out = new Out();

      

       //create a private inner object by 'new'

       //Out.PrivateIn privateIn=out.new PrivateIn();

       //->error: Out.PrivateIn is not visible.

 

       // create a default inner object by 'new'

       Out.DefaultIn defaultIn = out. new DefaultIn();

       //defaultIn.private_arg=0;->error:not visible

       defaultIn. default_arg = 0;

       //defaultIn.private_method();->error:not visible

       defaultIn.default_method();

 

       // create a private inner object by 'out's method'

       //Out.PrivateIn privateIn2 = out.getPrivateIn();

       //->error:Out.PrivateIn is not visible through out.getPrivateIn() is visible.

      

       // create a private inner object by 'out's method',

       // but use Interface reference to handle it

       InMethod privateIn=out.getPrivateIn();

       privateIn.public_method();

    }

}

方式一 OuterClassName.InnerClassName inner=new Ouer().new Inner();
使用方式一试图得到 private 内部类失败,根本得不到内部类的句柄。
//create a private inner object by 'new'

//Out.PrivateIn privateIn=out.new PrivateIn();

//->error: Out.PrivateIn is not visible.

    但是可以正常的访问 default 访问权限的内部类的对象。当然是访问不到它的 private 成员和 private 方法的。自然 protected public 的都可以访问。

 

方式二 通过外部类方法 get InnerInstance()
虽然可以调用外部类对象的 getInnerInstance() 方法,但由于得不到 private 内部类的句柄,所以此种方法无法创建 private 内部类的实例。
// create a private inner object by 'out's method'

//Out.PrivateIn privateIn2 = out.getPrivateIn();

//->error:Out.PrivateIn is not visible through out.getPrivateIn() is visible.
但由于所有的内部类都实现了接口 InMethod
<<interface>> InMethod.java

public interface InMethod {

    void public_method();

}

所以还是可以通过接口的引用访问到 private 内部类的 public 方法。自然 default protected public 的都可以访问这个 public 方法。
// create a private inner object by 'out's method',

// but use Interface reference to handle it

InMethod privateIn=out.getPrivateIn();

privateIn.public_method();
3. 不同包其他类的访问

在另一个包中建立一个类 DifferPackage.java
DifferPackage.java

package com.zj.other;

 

import com.zj.main.InMethod;

import com.zj.main.Out;

 

public class DifferPackage {

    public static void main(String[] args){

       //create an outer object

       Out out= new Out();

      

       //create a public inner object by 'new'

       Out.PublicIn publicIn=out. new PublicIn();

       publicIn. public_arg =0;

       publicIn.public_method();

      

       // create a public inner object by 'out's method'

       Out.PublicIn publicIn2 = out.getPublicIn();

       publicIn2. public_arg =0;

       publicIn2.public_method();

      

       //use Interface reference

       InMethod method;

       method=out.getPrivateIn();

       method.public_method();

       method=out.getDefaultIn();

       method.public_method();

       method=out.getProtectedIn();

       method.public_method();

       method=out.getPublicIn();

       method.public_method();

    }

}
通过 new 方式和 getInnerInstance() 方法只能访问 public 内部类的 public 成员和 public 方法;如果使用接口的引用,则可以访问所有 4 个内部类的 public 方法。
4. 不同包继承类的访问

在另一个包中建立一个类 DifferPackageExtend.java ,它继承自外部类 Out
DifferPackageExtend.java

package com.zj.other;

 

import com.zj.main.Out;

 

public class DifferPackageAndExtend extends Out{

    public static void main(String[] args){

       //create an DifferPackageAndExtend's object,which extends Out

       Out extend= new DifferPackageAndExtend();

      

       //create a protected inner object by 'new'

       //Out.ProtectedIn protectedIn=extend.new ProtectedIn();

       //->error:The constructor Out.ProtectedIn() is not visible

      

       // create a protected inner object by 'out's method'

       Out.ProtectedIn protectedIn=extend.getProtectedIn();

       protectedIn. public_arg =0;

       protectedIn.public_method();

    }

}
通过 new 方式,虽然可以得到内部类的句柄 Out.ProtectedIn ,但该内部类的构造子却不可见。
通过 getInnerInstance() 方法得到 protected 内部类的对象,但只能访问到 public 成员和 public 方法。由此可知, protected 内部类并不关心是否有其他类继承自它的外部类。所有 protected 访问权限不在此种情况下适用。