`

探讨Java内部类的可见性

阅读更多
转载自http://zhangjunhd.blog.51cto.com/113473/65624/
在Java中,当生成一个内部类的对象时,此对象与制造它的外部类通过外部类的.this保持着联系,因此该内部类对象可以访问其外部类对象的所有成员,包括private成员。

而该内部类对象对于其他类的对象的访问,遵照常规的访问权限语法,这一点也没有什么特别支持。这里需要探讨的是,外部类以及其他类的对象可以如何访问到某个内部类对象,即内部类的可见性问题。

下面是一个示例程序Out.java,其中包含了4个不同访问权限的内部类(private,default,protected,public),在每个内部类中,分别包含4个不同访问权限的成员与方法。在外部类Out中提供了得到内部类实例的方法。
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类的所有内部类。
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。
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。
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方法。

[b]4.不同包继承类的访问[\b]
在另一个包中建立一个类DifferPackageExtend.java,它继承自外部类Out。
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变量的可见性问题Java开发Java经验技巧共

    本主题将深入探讨Java中的变量可见性,包括其基本原理、规则以及如何有效地利用这些规则来优化代码。 首先,Java变量有四种基本类型的可见性: 1. **本地变量(Local Variables)**:在方法、构造器或者块内部定义...

    内部类 匿名内部类 内部接口 对比说明

    本文将详细探讨内部类、匿名内部类以及内部接口的对比和使用。 首先,让我们了解一下内部类的基本概念。内部类定义在其他类的内部,编译后会生成两个独立的类文件。内部类能够自由地访问外部类的所有成员,包括私有...

    理解java中的类的各种权限修饰符

    本文将详细探讨Java中的五种权限修饰符:`public`、`protected`、`default`(也称为包访问权限)、`private`以及`static`修饰类的情况,并通过实例来展示这些修饰符的具体应用。 #### 1. Public - **概述**: - `...

    java并发编程内部分享PPT

    这份“java并发编程内部分享PPT”显然是一个深入探讨这一主题的资料,旨在帮助开发者理解并掌握Java并发编程的核心概念和技术。 在Java并发编程中,首先我们需要了解的基本概念是线程。线程是操作系统分配CPU时间的...

    实验三:Java类与对象

    访问修饰符(public, private, protected, default)控制类、成员变量和方法的可见性。例如,`Monkey`类中的`name`, `weight`, `age`被声明为私有(`private`),意味着它们只能在类内部访问,而`love`被声明为静态...

    JAVA类的定义txt格式

    根据提供的文件信息,我们可以深入探讨Java类的基本定义与构造,以及如何在Java中定义一个类、类中的属性、构造函数、方法等基本概念。 ### Java类的定义 Java是一种面向对象的编程语言,其核心是类(Class)的...

    Java 对象和类的学习例子

    Java中的访问修饰符(public, private, protected, default)也是很重要的,它们决定了类的成员(字段和方法)对外部世界的可见性。例如,`public`成员可以被任何其他类访问,而`private`成员只能在定义它们的类内部...

    11.【final、权限、内部类】.zip

    这些修饰符决定了类、接口、方法和字段的可见性: - `public`:任何地方都可以访问。 - `private`:只在当前类中可访问,提供封装性。 - `protected`:在同一包内或不同包的子类中可访问。 - 默认:仅在同一包内的...

    07abril2021:Java对象类活动

    在Java中,我们通过访问修饰符(public, private, protected, default)来控制类成员的可见性,实现封装。 2. 继承:继承允许一个类(子类)从另一个类(父类)继承属性和行为,从而促进代码重用和模块化。子类可以...

    java多线程异步性

    volatile关键字用于确保多线程环境下的可见性和有序性。 七、并发集合 Java并发库提供了并发友好的集合类,如ConcurrentHashMap、CopyOnWriteArrayList和CopyOnWriteArraySet,它们在内部使用了锁或其他同步机制,...

    JAVA2_类_详解

    本篇文章将深入探讨Java中的类,包括类的定义、构造器、访问修饰符、成员变量、方法、继承、封装、多态等核心概念。 1. **类的定义** 类是创建对象的蓝图,它定义了对象的状态(数据成员或变量)和行为(成员函数...

    关于Java继承性的探讨.pdf

    Java的继承性是其面向对象特性的重要组成部分,它允许一个类(子类或派生类)从另一个类(父类或基类)继承属性和方法,从而实现代码的复用和扩展。这种机制大大提高了软件开发的效率和灵活性,同时也支持了面向对象...

    Java-Java面向对象编程教程

    访问修饰符控制类、字段和方法的可见性;内部类(包括成员内部类、局部内部类和匿名内部类)允许在类内部定义其他类,提供了更灵活的设计选项。 学习Java面向对象编程,需要掌握如何创建和操作类,理解类与对象的...

    java-concurrency编程内部分享_java实战_java_

    《JAVA并发编程实战》由Doug Lea撰写,是一本深入探讨Java并发编程的经典之作,对于Java开发者来说,这本书无疑是必备的参考资料。 在Java中,线程是并发的基本单元。Java提供了丰富的并发工具类和API,如`Thread`...

    java核心卷轴1--pdf版

    在Java中,我们使用访问修饰符(public, private, protected)来控制类的成员的可见性,以此实现封装。 3. 继承:继承允许子类从父类继承属性和行为,从而实现代码重用。在Java中,一个类可以使用extends关键字来...

    JAVA面向对象技术PPT

    在Java中,通过访问修饰符(public, private, protected)来控制类的成员对其他类的可见性,实现数据的安全性。 **2. 继承** 继承允许一个类(子类)从另一个类(父类)中继承属性和方法,从而实现代码的复用和...

    Java多线程编程核心技术_完整版_java_

    4. volatile与synchronized的区别:volatile只能保证可见性,而synchronized能保证可见性和原子性。 四、线程间的通信 1. wait()、notify()和notifyAll():这三个方法用于线程间的通信,它们必须在同步环境中使用。...

    华为 java 面试 题知识点

    本文将深入探讨部分关键知识点,包括类、内部类、接口、匿名内部类以及访问修饰符等,这些都是华为Java面试中常考的内容。 #### 类与对象 Java是一种面向对象的编程语言,类是定义对象属性和行为的模板。在示例...

    Java程序设计实验报告

    还会涉及到访问修饰符(public, private, protected, default),理解如何控制类的成员对外的可见性和可访问性,以及如何通过构造器和方法来实现类的实例化和操作。 实验五:权限控制与面向对象 实验五深入探讨Java...

Global site tag (gtag.js) - Google Analytics