`
explore
  • 浏览: 78452 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Java内部类可见性

    博客分类:
  • J2SE
阅读更多
转自:http://zhangjunhd.blog.51cto.com/113473/65624

在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访问权限不在此种情况下适用。
分享到:
评论

相关推荐

    探讨Java内部类的可见性

    这里需要探讨的是,外部类以及其他类的对象可以如何访问到某个内部类对象,即内部类的可见性问题。  下面是一个示例程序Out.java,其中包含了4个不同访问权限的内部类(private,default,protected,public),...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    11.2.2 类的可见性 293 11.2.3 final——让类不可被继承 295 11.2.4 理解final关键字 296 11.2.5 总结:类的修饰符 297 11.3 方法的修饰符 297 11.3.1 方法的访问控制符 298 11.3.2 public:没有限制的修饰符 ...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    11.2.2 类的可见性 293 11.2.3 final——让类不可被继承 295 11.2.4 理解final关键字 296 11.2.5 总结:类的修饰符 297 11.3 方法的修饰符 297 11.3.1 方法的访问控制符 298 11.3.2 public:没有限制的修饰符 ...

    java 编程入门思考

    2.6.1 名字的可见性 2.6.2 使用其他组件 2.6.3 static关键字 2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入HTML 2.8.4 @see:引用其他类 2.8.5 类文档标记 2.8.6 变量文档...

    Java初学者入门教学

    2.6.1 名字的可见性 2.6.2 使用其他组件 2.6.3 static关键字 2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入HTML 2.8.4 @see:引用其他类 2.8.5 类文档标记 2.8.6 变量文档...

    java联想(中文)

    2.6.1 名字的可见性 2.6.2 使用其他组件 2.6.3 static关键字 2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入HTML 2.8.4 @see:引用其他类 2.8.5 类文档标记 2.8.6 变量文档...

    JAVA面试题最全集

    一个“.java”原文件中是否可以包括多个类(不是内部类)? 53.掌握内部类和接口的概念 54.StringTokenizer类的使用 55.数据结构,如何遍历List中的元素? 如果要按照键值保存或者访问数据,使用什么数据结构? ...

    JAVA_Thinking in Java

    2.6.1 名字的可见性 2.6.2 使用其他组件 2.6.3 static关键字 2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入HTML 2.8.4 @see:引用其他类 2.8.5 类文档标记 2.8.6 变量文档...

    Thinking in java4(中文高清版)-java的'圣经'

    2.4.2 基本成员默认值 2.5 方法、参数和返回值 2.5.1 参数列表 2.6 构建一个Java程序 2.6.1 名字可见性 2.6.2 运用其他构件 2.6.3 static 关键字 2.7 你的第一个J ava程序 编译和运行 2.8 注释和嵌入式文档 2.8.1 ...

    Thinking in Java简体中文(全)

    2.6.1 名字的可见性 2.6.2 使用其他组件 2.6.3 static关键字 2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入HTML 2.8.4 @see:引用其他类 2.8.5 类文档标记 2.8.6 变量文档...

    Thinking in java(中文)

    类 2.4.1 字段和方法 2.5 方法、自变量和返回值 2.5.1 自变量列表 2.6 构建Java程序 2.6.1 名字的可见性 2.6.2 使用其他组件 2.6.3 static关键字 2.7 我们的第一个Java程序 2.8 注释和...

    Thinking in Java 中文第四版+习题答案

    2.6.1 名字的可见性 2.6.2 使用其他组件 2.6.3 static关键字 2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入 2.8.4 @see:引用其他类 2.8.5 类文档标记 2.8.6 变量文档标记...

    java 异常总结

    当一个应用试图访问、修改某个类的域(Field)或者调用其方法,但是又违反域或方法的可见性声明,则抛出该异常。 java.lang.IncompatibleClassChangeError 不兼容的类变化错误。当正在执行的方法所依赖的类定义发生...

    JAVA_Thinking in Java(中文版 由yyc,spirit整理).chm

    2.6.1 名字的可见性 2.6.2 使用其他组件 2.6.3 static关键字 2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入HTML 2.8.4 @see:引用其他类 2.8.5 类文档标记 2.8.6 变量文档...

    Think in Java(中文版)chm格式

    2.6.1 名字的可见性 2.6.2 使用其他组件 2.6.3 static关键字 2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入HTML 2.8.4 @see:引用其他类 2.8.5 类文档标记 ...

    [java]读书笔记整理:一切都是对象

    作用域决定了在其内定义的变量名的可见性和生命周期。在C,C++和java中,作用域由花括号的位置决定。例如: { int x=12; //只有x 可用 { int y=100; //x,y 都可用 } //只有x 可用 //y ...

    Thinking in Java(中文版 由yyc,spirit整理).chm

    2.6.1 名字的可见性 2.6.2 使用其他组件 2.6.3 static关键字 2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入HTML 2.8.4 @see:引用其他类 2.8.5 类文档标记 2.8.6 变量文档...

    spring-gradle-kotlin-multimodule:Spring-boot Gradle多模块项目展示了使用Kotlin可见性修改器在模块之间进行的隔离(内部)

    这是通过利用内部Kotlin可见性修饰符来完成的,该修饰符将可见性限制在当前模块的范围内(与Java的程序包保护相比,它提供了更多的隔离性-考虑有意创建与依赖于访问其程序包保护类的依赖项相同的程序包) 。...

    Java中Volatile关键字步骤

    基本概念 Java内存模型中的可见性,原子性和有序性 可见性:  可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉。通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚至是...

    超爽的自学课件(java)

    本章也向大家介绍了Java 1.1的“内部类”。 &lt;br&gt;(8) 第8章:对象的容纳 对一个非常简单的程序来说,它可能只拥有一个固定数量的对象,而且对象的“生存时间”或者“存在时间”是已知的。但是通常,我们的程序...

Global site tag (gtag.js) - Google Analytics