1.Nested Class
在Java程序中,被定义在一个类内部的类,称为内部类(Nested Class)。
内部类分为三种:
- Inner class,常见的内部类
- Anonymous Class,匿名类
- Static Nested Class,静态内部类
2.Inner class
代码示例:
class Outer{
class Inner{
}
}
特性:
- Inner类示例无法独立存在,必须依附outer类
Outer outer = new Outer("Nested"); // 实例化一个Outer
Outer.Inner inner = outer.new Inner(); // 实例化一个Inner
- Inner类除了指向自己实例的this指针,还隐含一个this指针指向Outer实例,可以通过Outer.this访问这个示例
- Inner类有一个专属权利,就是可以访问并修改Outer的private字段
3.Anonymous Class
Inner class 定义在类的内部,而Anonymous class定义在方法内。
代码示例:
void fun() {
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("Hello");
}
};
new Thread(r).start();
}
上述代码中,在方法内部实例化一个Runnable,runnable本身是接口,不可以被实例化。在这里实际上定义了一个实现Runnable接口的匿名类,通过new实例化该匿名类,然后转型为Runnable。
特性:
- 在定义匿名类的时候,就需要对其进行实例化
- JDK1.7之前,匿名类内部引用外部的变量,该变量需声明为final类型,JDK1.8后无需声明,编译器自动会加上final
针对对象来说,声明的变量是对象的引用(即地址),在匿名类内部不可修改对象引用,外部可进行修改
匿名类在引用外部变量时,实际上是对外部变量进行了拷贝操作,确保该值不可变或者引用指向的地址不可变 - 实现接口是匿名类最常见的使用形式,除以之外,继承类也是可以的
HashMap<String, String> map1 = new HashMap<>();
HashMap<String, String> map2 = new HashMap<>() {}; // 匿名类!
HashMap<String, String> map3 = new HashMap<>() { //匿名类,并通过静态代码块初始化map,注意不需要加static
{
put("A", "1");
put("B", "2");
}
};
4.Static Nested Class
类似于Inner class,但是用static修饰
代码示例:
class Outer{
static class Inner{
}
}
特性:
- 独立于Outer类存在,因此也没有Outer.this指向Outer类的实例
- 可访问Outer的private字段