定义
嵌套类,顾名思义,就是定义在一个类内部的类。
分类
定义在类的内部,就与类的成员(即属性和方法)“平起平坐”,而类的成员可分为静态成员和非静态成员,之于嵌套类,也是有如此相似的特点——嵌套类分为静态嵌套类和非静态嵌套类,非静态嵌套类又名内部类,而内部类中又有两种很特殊的内部类,即局部内部类和匿名内部类,因此,嵌套类的分类如下图所示:
共性
嵌套类与普通类既有共同点也有很多需要额外注意的地方,因此,本文为了能够教全面地点到这些异同,就先说说嵌套类的如下共性:
- 嵌套类可以拥有哪些类型的成员?
- 静态嵌套类:可以拥有静态成员和非静态成员
- 非静态嵌套类:只能拥有非静态成员
- 嵌套类能使用哪些修饰词?
- 嵌套类同样可用abstract、final来修饰
- 静态嵌套类和(普通)内部类可用public、protected、<默认>、private来修饰,从而控制它的访问权限。
public、protected、<默认>、private用来修饰类的成员,而嵌套类很像类的“第三种”成员,从这个角度看,就很容易理解这点。
详解
下面分别从定义嵌套类、创建嵌套类对象以及嵌套类和外部类的关系这三方面异议详解如上四种嵌套类。
静态嵌套类
- 1.定义
静态嵌套类在外部类定义成员的地方定义,形如:
class OuterClass {
……
static class StaticNestedClass{
……
}
……
}
- 2.创建对象
前文已经提到,静态嵌套类类似于静态属性和静态方法,因此,可以像它们一样直接通过类名来使用
(PS:关于这点,通过与后边介绍的内部类的使用就能有更深切的领会)
静态嵌套类对象的创建形如:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
- 3.与外部类的关系
静态嵌套类只能访问外部类的静态成员(包括静态属性和静态方法)。
想想这是为什么?如上所示,通过类名就可以直接创建静态嵌套类的对象,他与外部类的实例对象没有关系——静态嵌套类很“独立”,而非静态成员只有在创建了对象后才能通过对象名来访问。静态嵌套类在创建对象时,它的外部类可能没有创建对象,因此,就没有可供访问的非静态属性。
这就可以看出静嵌套类与它的外部类的关系比较弱。
内部类
- 1.定义
内部类和静态嵌套类一样,在外部类定义成员的地方定义,形如:
class OuterClass{
……
class InnerClass{
……
}
……
}
与静态嵌套类相比,它不需要用static关键字来修饰。
- 2.创建对象
内部类类似于普通的属性和方法,因此,在创建它的对象时,首先要创建它的外部类的对象,然后再用该对象创建内部类的对象,形如:
OuterClass outerObject = new OuterObject();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
要注意outerObject.new这部分的写法。
由此可见,与前面讲到的静态嵌套类对象的创建有很明显的区别。
- 3.与外部类的联系
内部类可以直接访问外部类的所有成员(包括静态和非静态的属性和方法),
想想这是为什么?因为在创建内部类的对象时,首先要创建外部类的对象,因此,有可以被访问的外部类的属性和方法。
局部内部类
- 1.定义
局部内部类是定义在方法体中的内部类。定义局部内部类的形如:
class OuterClss{
……
public void method(){
……
class LocalInnerClass{
……
}
……
}
……
}
- 2.使用范例
注意,局部内部类很像局部变量,不能从方法外访问,因而,它的使用形如:
public class Example {
public static void main(String[] args) {
say();
}
private static void say() {
class People {
private String name = "Jully";
private int age = 18;
protected void introduce() {
System.out.println("大家好,我是" + name + ",我今年" + age + "岁");
}
}
People people = new People();
people.introduce();
}
}
程序运行结果如下图:
- 3. 注意点
局部内部类只能访问方法的final类型的局部变量。
匿名内部类
匿名内部类的定义和使用常如如下形式:
public class OuterClass {
……
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("这是一个实现了Runnable接口的匿名内部类中的Run方法");
}
});
……
}
匿名内部类可以用来继承一个类或实现一个接口,但不能同时实现这两种功能,上面的例子是用一个类实现了Runnable接口,同时也创建了一个匿名对象,但这个类是匿名的。
博主水平有限,加之时间仓促,错漏难免,望不吝赐教!