探讨Java内部类的可见性

简介:
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 访问权限不在此种情况下适用。


本文转自zhangjunhd51CTO博客,原文链接:http://blog.51cto.com/zhangjunhd/65624,如需转载请自行联系原作者
相关文章
|
1月前
|
Java
java中,剩下的这两个内部类不太好理解!
java中,剩下的这两个内部类不太好理解!
12 0
|
1月前
|
Java 编译器
java中常见的几种内部类,你会几个?(未完)
java中常见的几种内部类,你会几个?(未完)
14 1
|
4月前
|
Java 数据安全/隐私保护
【零基础学Java】—内部类的概念与分类(三十)
【零基础学Java】—内部类的概念与分类(三十)
|
14天前
|
安全 Java 编译器
接口之美,内部之妙:深入解析Java的接口与内部类
接口之美,内部之妙:深入解析Java的接口与内部类
35 0
接口之美,内部之妙:深入解析Java的接口与内部类
|
16天前
|
Java API
Java基础—笔记—内部类、枚举、泛型篇
本文介绍了Java编程中的内部类、枚举和泛型概念。匿名内部类用于简化类的创建,常作为方法参数,其原理是生成一个隐含的子类。枚举用于表示有限的固定数量的值,常用于系统配置或switch语句中。泛型则用来在编译时增强类型安全性,接收特定数据类型,包括泛型类、泛型接口和泛型方法。
9 0
|
16天前
|
存储 Java
java接口和内部类
java接口和内部类
|
1月前
|
Java 编译器
详解java各种内部类
详解java各种内部类
|
1月前
|
设计模式 Java
JAVA内部类
JAVA内部类
10 1
|
2月前
|
Java
JAVA基础--内部类和静态内部类、单例模式---静态内部类剖析
JAVA--内部类和静态内部类、单例模式---静态内部类剖析
38 9
|
4月前
|
Java
【Java基础】类名、抽象类、接口名的参数传递及成员内部类、局部内部类和匿名内部类的使用
【Java基础】类名、抽象类、接口名的参数传递及成员内部类、局部内部类和匿名内部类的使用
40 0