匿名内部类适合创建那种只需要一次使用的类,匿名内部类的语法有点奇怪,创建匿名内部类时会立即创建一个该类的实例,这个类定义立即消失,匿名内部类不能重复使用。
定义匿名内部类的格式如下:
new 父类构造器(实参列表) | 实现接口()
{
//匿名内部类的类体部分
}
从上面定义可以看出,匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类,或实现一个接口。
关于匿名内部类还有如下两条规则:
(1)匿名内部类不能是抽象类,因为系统在创建匿名内部类的时候,会立即创建匿名内部类的对象。因此不允许将匿名内部类定义成抽象类。
(2)匿名内部类不能定义构造器,因为匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义实例初始化块,通过实例初始化块来完成构造器需要完成的事情。
最常用的创建匿名内部类的方式是需要创建某个接口类型的对象,如下程序所示:
interface Product
{
public double getPrice();
public double getName();
}
public class TestAnonymous
{
public void test(Product p)
{
System.out.println("购买了一个"+p.getName()+",花掉了"+p.getPrice());
}
public static void main(String[] args)
{
TestAnonymous ta=new TestAnonymous();
//调用test方法时,需要传入一个Product参数,此处传入其匿名实现类的实例
ta.test(new Product()
{
public double getPrice()
{
return 567.8;
}
public String getName()
{
return "AGP显卡";
}
});
}
}
上面程序中的TestAnonymous类定义了一个test方法,该方法需要一个Product对象作为参数,但Product只是一个接口,无法直接创建对象,因此此处考虑创建一个Product接口实现类的对象传入该方法--如果这个Product接口实现类需要重复使用,则应该将该实现类定义成一个独立类;如果这个Product接口实现类只需一次使用,则可采用上面程序的方式,定义一个匿名内部类。
正如上面程序中看到,定义匿名内部类无需class关键字,而是在定义匿名内部类时直接生成该匿名内部类的对象。上面红色粗体字代码部分是匿名内部类的类体部分。
由于匿名内部类不都是抽象类,所以匿名内部类必须实现它的抽象父类或者接口里包含的所有抽象方法。如果有需要,也可以重写父类的普通方法。
对于上面创建Product实现类对象的代码,可以拆分成如下代码:
class AnonymousProduct implements Product
{
public double getPrice()
{
return 567.8;
}
public String getName()
{
return "AGP显卡";
}
}
ta.test(new AnonymousProduct());
当通过实现接口来创建匿名内部类时,匿名内部类也不能显示创建构造器,因此匿名内部类只有一个隐式的无参构造器,故new接口名后的括号里不能传入参数值。如果匿名内部类需要访问外部类的局部变量,则必须使用final修饰符来修饰外部类的局部变量,否则系统将报错。看下面程序:interface A
{
void test();
}
public class TestA
{
public static void main(String[] args)
{
int age=0;
A a=new A();
{
public void test()
{
//下面语句将提示错误,匿名内部类内访问局部变量必须使用final修饰
System.out.println(age);
}
};
}
}
上面红色粗体字代码是匿名内部类访问了外部类的局部变量,由于age变量没有使用final修饰符修饰,所以粗体字代码将引起编译异常。