问:简述一下内部类的实质是什么?

书上看到的一个问题,整理下来


简述一下内部类的实质是什么?

内部类是Java的类的一种形式,它的使用语法比较奇怪


分析:

package abc;
class A {//定义外部类A
   class B {//定义内部类B
      ...
   }
}

对于B类来说,它的完整类名就是abc.A.B,命名空间进一步缩小了,并且B对A产生了一种依赖关系,只有A存在的时候B才存在。

根据内部类定义结构的不同, 可以把内部类分为两种:成员式和局部式。成员式内部类指的是它们定义的地方与成员变量和成员方法类似,就好像一个类的成员一样。局部式内部类则是定义在方法体中,仅属于局部范围所有。

然后成员式内部类又分为:静态内部类和成员内部类。局部式又可以分为:普通局部内部类和匿名内部类。


1、静态内部类

package abc;
class Outter {//定义外部类Outter
	static class Inner {//定义静态内部类Inner
		...
	}
}

在外部类加载的时候,静态内部类也随之加载,它的完整类名是abc.Outter.Inner,编译后的class文件名为“Outer$Inner.class”。由于静态内部类是静态的,所以它无法访问外部类的非静态成员。其实,静态内部类相对于外部类来说,几乎是独立的,它可以在没有外部类对象的情况下,单独创造一个内部类的对象。(某种程度上来说,公开的静态内部类就相当于一个普通的类)

总结一下,静态内部类相对于外部类来说,仅仅是包含关系,缩小了命名空间,完整的类名中多了一个外部类的名称。本质上是独立的两个类,JVM也不知道他们两个有包含关系。


2、成员内部类

没有使用static修饰的内部类,例如下面的代码:

package abc;
class Outter {//定义外部类Outter
	class Inner {//定义成员内部类Inner
		...
	}
}

此时的内部类需要等外部类创建了对象以后才会被加载到JVM中,它属于外部类的某个实例,因此它可以访问外部类的静态和非静态成员。创建成员内部类的时候,语法比较特殊,首先创建一个外部类的实例,然后用这个实例调用new语句,代码如下:

public static void main(String[] args) {
		Outter o = new Outter();//创建外部类实例
		Outter.Inner i = o.new Inner();//创建内部类实例
	}
对于成员内部类的构造方法来说,系统会自动为他加上一个外部类的参数以及一个外部类的成员变量,这是为了遵循先有外部类实例才能有内部类实例的原则,代码如下:

class Inner(Outter o){//成员内部类的本质构造方法
		this.o = o;
	}
当内部类访问外部类的成员时,则是通过该自动添加的成员变量进行访问,就好像下面的代码

o.abc();


3、局部内部类

局部内部类就没有范围的概念了,它仅在定义它的方法中有效,例如下面的代码:

public void adc(){ //成员方法
		class MyLocal{  //定义局部内部类
			...			//局部内部类体
		}
	}
本质上来说,局部内部类它也是以独立的类,只不过它的一些使用受到了限制,例如,它不能使用static关键字,只能使用final、abstract关键字,仅可以访问外部类带有final关键字的局部变量,因为它访问的是一个字面量或镜像,该局部变量已经不存在了。但是,它可以任意的访问外部类对象的成员变量。

说明:与成员内部类类似,局部内部类的构造方法也会自动加上一个外部类型的参数,以及为该内部类加一个外部类型的成员变量。

当局部内部类定义在静态方法中时就相当于静态内部类:当定义在普通的成员方法中时,则相当于成员内部类。


4、匿名内部类

如果一个局部内部类没有名字,则它就是匿名内部类,例如下面的代码:

public void adc(){ //成员方法
		new OneInterface(){  //直接new一个接口
			public void interMethod(){//接口方法
				...
			}
		};
	}
在以上代码中,匿名内部类的定义和使用根本没有出现class关键字,但事实上它还是创建了。该类实现了OneInterface接口,直接在方法体中就提供具体的实现,如果需要提供构造方法的参数,则直接在OneInterface后边的那个括号中提供即可,显得非常的灵活。其实,它的工作原理相当于局部内部类,只是没有一个具体的名字而已,外部也无法直接使用它。

注意:匿名内部类编译后的class文件的命名是按照匿名内部类的排列顺序来进行的,直接在外部类后面加上“$”和序号,例如Outter$1.class。


【答案】

内部类根据定义的情况可以分为以下4种。

(1)静态内部类:它相当于外部类的静态成员一样,使用static修饰的内部类,它隶属于外部类,使用起来相当于一个独立的外部类。

(2)成员内部类:它相当于外部类普通的成员一样,隶属于外部类的具体对象,在定义它的时候,需要先创建外部类对象,再创建它的实例。

(3)局部内部类:它定义在一个方法的方法体中,它往往仅作为方法短暂的使用,只能访问用final修饰的局部变量。

(4)匿名内部类:它也定义在方法体中,但是没有一个具体的名字,具有非常大的灵活性,工作本质与局部内部类类似。




  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值