6.7.5 Java8改进的匿名内部类

6.7.5 Java8改进的匿名内部类

匿名内部类适合创建那种只需要一次使用的类,匿名内部类不能重复使用。

定义匿名内部类的格式

创建接口的匿名内部类

1
2
3
4
new 实现接口()
{
//匿名内部类类体部分
}

实现接口方式接口名后面的括号里不能传入参数

通过实现接口来创建匿名内部类时,由于接口中不能定义构造器,因此匿名内部类只有一个隐式的无参数构造器,故new 接口名后的括号里不能传入参数值

创建抽象类的匿名内部类

1
2
3
4
new 父类构造器(实参列表)
{
//匿名内部类类体部分
}

抽象类的匿名内部类可以调用带参构造器

由于抽象类可以定义构造器,并且抽象类的构造器是提供给子类调用的,所以,创建抽象类的匿名内部类时:
new 抽象类名后面的括号中可以传入参数,也可以不传入参数

  • 传入参数时,将调用对应的带参构造器。
  • 不传入参数时,将调用无参构造器

匿名内部类规则

关于匿名内部类还有如下两条规则。

  • 匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象。因此不允许将匿名内部类定义成抽象类
  • 匿名内部类不能定义构造器。由于匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义初始化块,可以通过实例初始化块来完成构造器需要完成的事情

匿名内部类必须实现所有抽象方法

由于匿名内部类不能是抽象类,所以匿名内部类必须实现它的抽象父类或者接口里包含的所有抽象方法。如果有需要,也可以重写抽象父类中的普通方法

匿名内部类不可以修改局部变量的值

java8之前被匿名内部类访问的局部变量必须 手动 用final修饰

Java8之前,Java要求被局部内部类匿名内部类访问的局部变量必须使用final修饰。

java8后被匿名内部类访问的局部变量会 自动 加上final修饰

Java8开始,被局部内部类匿名内部类访问的局部变量可以不显示用final修饰。如果局部变量被匿名内部类访问,那么该局部变量相当于自动使用了final修饰
Java8将这个功能称为"effectively final",它的意思是对于被匿名内部类访问的局部变量,可以用final修饰,也可以不用final修饰,但必须按照有final修饰的方式来用。
也就是被匿名内部类访问的局部变量一旦被赋值一次后,以后不能再重新赋值

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
interface A {
void test();
}

public class ATest {
public static void main(String[] args) {
int age = 8; // ①
// 下面代码将会导致编译错误
// 由于age局部变量被匿名内部类访问了,因此age相当于被final修饰了
// age = 2;
A a = new A() {
public void test() {
// 在Java 8以前下面语句将提示错误:age必须使用final修饰
// 从Java 8开始,匿名内部类、局部内部类允许访问非final的局部变量
System.out.println(age);
}
};
a.test();
}
}