程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 探討Java內部類的可見性

探討Java內部類的可見性

編輯:關於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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved