匿名内部类适合建立那种只须要一次使用的类,例如命令模式时所须要的Command对象。匿名内部类的语法有点奇怪,建立匿名内部类时会当即建立一个该类的实例,这个类定义当即消失,匿名内部类不能重复使用。
定义匿名内部类的格式以下:this
源码打印?.net
- new 父类构造器(参数列表)|实现接口()
- {
- //匿名内部类的类体部分
- }
从上面定义能够看出,匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类,或实现一个接口。
关于匿名内部类还有以下两条规则:
1)匿名内部类不能是抽象类,由于系统在建立匿名内部类的时候,会当即建立内部类的对象。所以不容许将匿名内部类
定义成抽象类。
2)匿名内部类不等定义构造器,由于匿名内部类没有类名,因此没法定义构造器,但匿名内部类能够定义实例初始化块,
经过实例初始化块来完成构造器须要完成的事情。
最经常使用的建立匿名内部类的方式是须要建立某个接口类型的对象,以下程序所示:对象
源码打印?继承
- interface Product{
- public double getPrice();
- public String 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();
- ta.test(new Product(){
- public double getPrice(){
- return 567;
- }
- public String getName(){
- return "AGP显卡";
- }
- });
- }
- }
上面程序中的TestAnonymous类定义了一个test方法,该方法须要一个Product对象做为参数,但Product只是一个接口,
没法直接建立对象,所以此处考虑建立一个Product接口实现类的对象传入该方法---若是这个Product接口实现类须要重复
使用,则应该经该实现类定义一个独立类;若是这个Product接口实现类只需一次使用,则可采用上面程序中的方式,定义
一个匿名内部类。
正如上面程序中看到,定义匿名类不须要class关键字,而是在定义匿名内部类时直接生成该匿名内部类的对象。上面
粗体字代码部分就是匿名类的类体部分。
因为匿名内部类不能是抽象类,因此匿名内部类必须实现它的抽象父类或者接口里包含的全部抽象方法。
对于上面建立Product实现类对象的代码,能够拆分红以下代码:接口
源码打印?get
- class AnonymousProduct implements Product{
- public double getPrice(){
- return 567;
- }
- public String getName(){
- return "AGP显卡";
- }
- }
- ta.test(new AnonymousProduct());
当经过实现接口来建立匿名内部类时,匿名内部类也不能显示建立构造器,所以匿名内部类只有一个隐式的无参数构造
器,故new接口名后的括号里不能传入参数值。
但若是经过继承父类来建立匿名内部类是,匿名内部类将拥有和父类类似的构造器,此处的类似指的是拥有相同的形参
列表。源码
源码打印?io
- abstract class Device{
- private String name;
- public Device(){
- }
- public Device(String name){
- this.name = name;
- }
- public abstract double getPrice();
- //此处省略了name属性的setter和getter方法
- }
- public class AnonymousInner{
- public void test(Device d){
- System.out.println("购买了一个"+d.getName()+",花掉了"+d.getPrice());
- }
- public static void main(String[] args){
- AnonymousInner ai = new AnonymousInner();
- //调用有参数的构造器建立Device匿名实现类的对象
- ai.test(new Device("电子示波器"){
- public double getPrice(){
- return 67;
- }
- });
- //调用无参数的构造器建立Device匿名实现类的对象
- Device d = new Device(){
- //初始化块
- {
- System.out.println("匿名内部类的初始化块...");
- }
- //实现抽象方法
- public double getPrice(){
- return 56;
- }
- public Sting getName(){
- return "键盘";
- }
- };
- ai.test(d);
- }
- }
上面程序建立了一个抽象父类Device,这个抽象父类里包含两个构造器:一个无参数的,一个有参数的。当建立以Device
为父类的匿名内部类时,便可以传入参数(如上面程序中第一段粗体字部分),也能够不传入参数(如上面程序中第二段粗体
字部分)。
当建立匿名内部类时,必须实现接口或抽象父类里的全部抽象方法。若是有须要,也能够重写父类中的普通方法,如上面
程序的第二段粗体字代码部分,匿名内部类重写了抽象父类Device类的getName方法,其中getName方法并非抽象方法。
若是匿名内部类须要访问外部类的局部变量,则必须使用final修饰符来修饰外部类的局部变量,
不然系统将报错。编译
源码打印?class
- interface A{
- void test();
- }
- public class TestA{
- public static void main(Strign[] args){
- int age = 0;
- A a = new A(){
- public void test(){
- //下面语句将提示错误:匿名内部类内访问局部变量必须使用final修饰
- System.out.println(age);
- }
- };
- }
- }
上面程序中粗体子代码是匿名内部类访问了外部类的局部变量,因为age变量没有使用final修饰符修饰,因此粗体字代码将 引发编译异常。