【Java面试题】11 什么是内部类?Static Nested Class 和 Inner Class的不同。
Inner Class(内部类)定义在类中的类。 (一般是JAVA的说法)
Nested Class(嵌套类)是静态(static)内部类。(一般是C++的说法)
静态内部类:1 创建一个static内部类的对象,不需要一个外部类对象2 不能从一个static内部类的一个对象访问一个外部类对象
Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。
内部类:就是在一个类的内部定义的类,
A.非静态内部类中不能定义静态成员(静态对象是默认加载,那么静态内部类应该先于外部类被加载到内存中)
当内部类中如果有静态成员时,该内部类也必须是静态的。而静态内部类只能访问外部类中的静态成员。 会出现两种情况:
1,内部类静态,但是方法没静态。该方法需要被对象调用执行。
Outer.Inner in = new Outer.Inner();//产生了一个静态内部类对象。
in.show();
2,内部类静态,而且方法也是静态的。静态内部类随着对象的加载就已经存在了,静态方法随着内部类的加载也存在了。这时是不需要对象的。
Outer1.Inner.show();
B.内部类可以直接访问外部类中的成员变量
非静态的内部类之所以可以直接访问外部类中的成员,那是因为内部类中都持有一个外部类对象引用:外部类名.this.变量名
静态内部类之所以可以直接访问外部类中的静态成员,其实持有的是外部类名。
C.内部类可以定义在外部类的方法外面,也可以定义在外部类的方法体中,如下所示:
在方法体外面定义的内部类的访问类型可以是public,protected,默认的,private等4种类型,它们决定这个内部类的定义对其他类是否可见;对于这种情况,我们也可以在外面创建内部类的实例对象,一定要先创建外部类的实例对象,然后用这个外部类的实例对象去创建内部类的实例对象,代码如下:
Outer outer = new Outer();
Outer.Inner1 inner1 = outer.new Innner1();
在方法内部定义的内部类前面不能有访问类型修饰符,但前面可以使用final或abstract修饰符。这种内部类对其他类是不可见的其他类无法引用这种内部类,但是这种内部类创建的实例对象可以传递给其他类访问。这种内部类必须是先定义,后使用,即内部类的定义代码必须出现在使用该类之前,这与方法中的局部变量必须先定义后使用的道理也是一样的。这种内部类可以访问方法体中的局部变量,但是,该局部变量前必须加final修饰符。
在方法体内部还可以采用如下语法来创建一种匿名内部类,没有名字的内部类,即定义某一接口或类的子类的同时,还创建了该子类的实例对象,无需为该子类定义名称:
public class Outer{
public void start(){
new Thread(
new Runable(){
public void run(){};
}).start();
}
}
Static Nested Class,它不再具有内部类的特性,从狭义上讲,它不是内部类。Static Nested Class与普通类在运行时的行为和功能上没有什么区别,只是在编程引用时的语法上有一些差别:
1.它可以定义成public、protected、默认的、private等多种类型,而普通类只能定义成public和默认的这两种类型。
2.在外面引用Static Nested Class类的名称为“外部类名.内部类名”。
3.在外面不需要创建外部类的实例对象,就可以直接创建Static Nested Class,例如,假设Inner是定义在Outer类中的Static Nested Class,那么可以使用如下语句创建Inner类:
Outer.Inner inner = new Outer.Inner();
4.由于static Nested Class不依赖于外部类的实例对象,所以,static Nested Class能访问外部类的非static成员变量。
5.当在外部类中访问Static Nested Class时,可以直接使用Static Nested Class的名字,而不需要加上外部类的名字了,在Static Nested Class中也可以直接引用外部类的static的成员变量,不需要加上外部类的名字。
在静态方法中定义的内部类也是Static Nested Class,这时候不能在类前面加static关键字,静态方法中的Static Nested Class与普通方法中的内部类的应用方式很相似,它除了可以直接访问外部类中的static的成员变量,还可以访问静态方法中的局部变量,但是,该局部变量前必须加final修饰符。
备注:内部类的总体方面的特点:两个地方可以定义,可以访问外部类的成员变量,不能定义静态成员,这是大的特点。然后再说一些细节方面的知识,例如,几种定义方式的语法区别,静态内部类,以及匿名内部类。