在
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
访问权限不在此种情况下适用。
本文转自zhangjunhd51CTO博客,原文链接:http://blog.51cto.com/zhangjunhd/65624,如需转载请自行联系原作者