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访问权限不在此种情况下适用。
http://zhangjunhd.blog.51cto.com/113473/65624

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值