探讨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,如需转载请自行联系原作者
相关文章
|
3天前
|
缓存 Java 程序员
Java内存模型深度解析:可见性、有序性和原子性
在多线程编程中,正确理解Java内存模型对于编写高效且无bug的并行程序至关重要。本文将深入探讨JMM的三大核心特性:可见性、有序性和原子性,并结合实例分析如何利用这些特性来避免常见的并发问题。
5 1
|
8天前
|
设计模式 Java 编译器
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
|
2天前
|
存储 缓存 Java
【Java并发基础】Java内存模型解决有序性和可见性
【Java并发基础】Java内存模型解决有序性和可见性
|
26天前
|
Java 编译器
24. 【Java教程】内部类
24. 【Java教程】内部类
15 2
|
5天前
|
Java
Java内部类相关内容总结和解读
Java内部类相关内容总结和解读
|
6天前
|
存储 Java
Java 五种内部类演示及底层原理详解
Java 五种内部类演示及底层原理详解
6 0
|
29天前
|
Java 程序员
Java的内部类与匿名类的技术性文章
Java的内部类与匿名类的技术性文章
19 1
|
1月前
|
Java
Java内部类(成员内部类、静态内部类、局部内部类、局部内部类)
Java内部类(成员内部类、静态内部类、局部内部类、局部内部类)
16 3
|
1月前
|
Java
一文搞懂内部类(Java)
Java内部类包括成员内部类、静态内部类、局部内部类和匿名内部类。成员内部类能访问外部类的所有成员,可以通过外部类实例创建。静态内部类与外部类实例无关,可直接访问外部类的静态成员。局部内部类仅限方法内使用,能访问最终变量。匿名内部类无名称,常用于一次性实现接口或抽象类,需外部类成员为final。
13 1
|
1月前
|
存储 Java API
【JAVA学习之路 | 提高篇】[内部类与常见API]String类
【JAVA学习之路 | 提高篇】[内部类与常见API]String类