内部类分为三种:嵌入类、内部成员类和本地类。
1.嵌入类:用static修饰的内部类就是嵌入类。它和外部类的其他成员属性和方法在同一层次上。嵌入类可以定义任何类型的成员属性和方法。但是嵌入类不能和它的外部类同名,也不能和其他成员同名。由于嵌入类本身就是外部类的成员,所以可以具有一般成员的访问权限,包括public、protected、private和默认。而一般顶层类只具有public或默认权限。
2.内部成员类:不用stacic修饰的内部类就是内部成员类。它的地位与类的实例成员相当,所以也被称为内部实例成员类。内部成员类和嵌入类的区别在于:内部成员类不允许有静态成员,但是可以定义静态的常量。
3.本地类:定义在方法中的内部类就是本地类。本地类不能用static修饰。和内部成员类一样,本地类不允许有静态成员,但是可以定义静态的常量。本地类的作用域是定义它的方法,所以它没有访问类型。本地类的地位相当于定义了一个局部数据类型。
内部类能拥有的成员 | ||||||
静态常量 | 静态变量 | 实例变量 | 实例常量 | 静态方法 | 实例方法 | |
嵌入类 | √ | √ | √ | √ | √ | √ |
内部成员类 | √ | √ | √ | √ | ||
本地类 | √ | √ | √ | √ |
内部类访问外部类的成员:内部类相当于外部类的一个普通成员,因此,内部类访问其他成员是,不受访问权限修饰符限制。但是,它仍受到static的限制。
嵌入类本身用static修饰,所以编译器认为它所有的成员都处于静态环境中,因此,只能访问外部类的静态成员,而不允许访问实例成员。
内部成员类不能定义静态成员,但是它的实例方法可以访问外部类的静态和实例成员。
实例方法中的本地类可以访问外部类的任意成员;静态方法中的本地类只能访问外部类的静态成员。
内部类访问外部类成员时的限制 | ||||||
静态常量 | 静态变量 | 实例变量 | 实例常量 | 静态方法 | 实例方法 | |
嵌入类 | √ | √ | √ | |||
内部成员类 | √ | √ | √ | √ | √ | √ |
实例方法中的本地类 | √ | √ | √ | √ | √ | √ |
静态方法中的本地类 | √ | √ | √ |
内部类之间的相互使用
嵌入类是静态的,所以只能使用其他嵌入类,不允许使用内部成员类。内部成员类则可以使用嵌入类和其他的内部成员类。本地类的作用域只限于定义它的方法,所以嵌入类和内部成员类都不能使用本地类。本地类快一岁一使用嵌入类,但是在使用内部成员类时,收到方法本身类型的限制。实例方法中的本地类才能使用内部成员类。统一方法总的本地类可以相互使用。
class Outer_8{
//定义内部成员类
class Inner {
NestedButNotInner oa =new NestedButNotInner(); //内部成员类可以使用嵌入类
public void call(){
Inner oa = new Inner(); //可以使用内部成员类
vfun(); //可以调用实例方法
sfun(); //可以调用静态方法
}
}
//定义嵌入类
static class NestedButNotInner {
//错误,嵌入类不允许使用内部成员类
// Inner a =new Inner();
public void call(){
NestedButNotInner oa =new NestedButNotInner(); //可以使用嵌入类
sfun(); //可以调用静态方法
//错误,不能调用实例方法
//vfun();
}
}
//定义实例方法
public void vfun(){
class localize{ //这是本地类
Inner a = new Inner(); //正确
NestedButNotInner b =new NestedButNotInner(); // 正确
}//本地类结束
System.out.println("这是外部类的成员方法");
}
//定义静态方法
public static void sfun(){
class localize1{
//错误,不允许使用内部成员类
// Inner a = new Inner();
NestedButNotInner b =new NestedButNotInner(); // 正确
}//本地类结束
class localize2{
localize1 oa =new localize1(); //使用同一方法中的本地类,正确
}
localize2 b=new localize2(); //正确
System.out.println("这是外部类的成员方法");
}
}
//定义内部成员类
class Inner {
NestedButNotInner oa =new NestedButNotInner(); //内部成员类可以使用嵌入类
public void call(){
Inner oa = new Inner(); //可以使用内部成员类
vfun(); //可以调用实例方法
sfun(); //可以调用静态方法
}
}
//定义嵌入类
static class NestedButNotInner {
//错误,嵌入类不允许使用内部成员类
// Inner a =new Inner();
public void call(){
NestedButNotInner oa =new NestedButNotInner(); //可以使用嵌入类
sfun(); //可以调用静态方法
//错误,不能调用实例方法
//vfun();
}
}
//定义实例方法
public void vfun(){
class localize{ //这是本地类
Inner a = new Inner(); //正确
NestedButNotInner b =new NestedButNotInner(); // 正确
}//本地类结束
System.out.println("这是外部类的成员方法");
}
//定义静态方法
public static void sfun(){
class localize1{
//错误,不允许使用内部成员类
// Inner a = new Inner();
NestedButNotInner b =new NestedButNotInner(); // 正确
}//本地类结束
class localize2{
localize1 oa =new localize1(); //使用同一方法中的本地类,正确
}
localize2 b=new localize2(); //正确
System.out.println("这是外部类的成员方法");
}
}
在外部使用内部类
嵌入类和内部成员类,如果它们的访问权限不是private,则可以在外部使用这些类。但是本地类外部是无法使用的。嵌入类可以像使用静态成员一样,通过“外部类名.嵌入类名”的方式使用,但是内部成员类必须通过外部类的实例进行引用。
class useInner{
public static void main(String argv[]){
Outer_8.NestedButNotInner oa = new Outer_8.NestedButNotInner(); //嵌入类可以直接用
Outer_8.Inner ob = new Outer_8().new Inner(); //内部成员类必须通过外部类创建
oa.call();
ob.call();
}
}
public static void main(String argv[]){
Outer_8.NestedButNotInner oa = new Outer_8.NestedButNotInner(); //嵌入类可以直接用
Outer_8.Inner ob = new Outer_8().new Inner(); //内部成员类必须通过外部类创建
oa.call();
ob.call();
}
}
匿名内部类
匿名内部类和一般创建对象的形式相似,唯一的区别是在于匿名内部类后面有大括号括起来的类体。
superClassName oa = new superClassName( 参数 ) { 类体 }
由于匿名类在创建的同事必须要创建对象,所以不能用static修饰。
public interface onlyShow{
void showMsg();
}
void showMsg();
}
public class anonymousInner{
static onlyShow st = new //创建匿名类的对象,这是一个类的成员
onlyShow() { //定义匿名内部类
public void showMsg() {
System.out.println("这是一个位于外部类中的匿名内部类.");
}
}; //匿名类定义结束,注意它末尾的分号
public static void main(String args[]){
onlyShow oa = new //创建匿名类的对象
onlyShow(){ //定义匿名内部类
public void showMsg(){
System.out.println("这是一个位于方法中的匿名内部类.");
}
}; //匿名类定义结束,注意它末尾的分号
oa.showMsg(); //使用其中的方法
st.showMsg();
}
}
static onlyShow st = new //创建匿名类的对象,这是一个类的成员
onlyShow() { //定义匿名内部类
public void showMsg() {
System.out.println("这是一个位于外部类中的匿名内部类.");
}
}; //匿名类定义结束,注意它末尾的分号
public static void main(String args[]){
onlyShow oa = new //创建匿名类的对象
onlyShow(){ //定义匿名内部类
public void showMsg(){
System.out.println("这是一个位于方法中的匿名内部类.");
}
}; //匿名类定义结束,注意它末尾的分号
oa.showMsg(); //使用其中的方法
st.showMsg();
}
}