在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