Java匿名内部类原理与用法详解
本文实例讲述了Java匿名内部类原理与用法。分享给大家供大家参考,具体如下:
一点睛
匿名内部类适合创建那种只需要一次使用的类,定义匿名内部类的语法格式如下:
new父类构造器(实参列表)|实现接口() { //匿名内部类的类体部分 }
从上面的定义可以看出,匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类,或实现一个接口。
两条规则。
- 匿名内部类不能是抽象类。
- 匿名内部类不能定义构造器。由于匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以初始化块,可以通过初始化块来完成构造器需要完成的工作。
二实战
1点睛
最常用的创建匿名内部类的方式是创建某个接口类型的对象。
2代码
interfaceProduct { publicdoublegetPrice(); publicStringgetName(); } publicclassAnonymousTest { publicvoidtest(Productp) { System.out.println("购买了一个"+p.getName() +",花掉了"+p.getPrice()); } publicstaticvoidmain(String[]args) { AnonymousTestta=newAnonymousTest(); //调用test()方法时,需要传入一个Product参数, //此处传入其匿名内部类的实例 ta.test(newProduct() { publicdoublegetPrice() { return567.8; } publicStringgetName() { return"AGP显卡"; } }); } }
3运行
购买了一个AGP显卡,花掉了567.8
4说明
定义匿名内部类无须class关键字,而是在定义匿名内部类时直接生成该匿名内部类的对象。
由于匿名内部类不能是抽象类,所以匿名内部类必须实现它的抽象父类或接口里包含的所有抽象方法。
三实战
1点睛
当通过接口来创建匿名内部类时,匿名内部类不能显示创建构造器,因此匿名内部类里只有一个隐式的无参构造器,故new接口名后的括号里不能传入参数值。
如果通过继承父类来创建匿名内部类时,匿名内部类将拥有和父类相似的构造器,此处的相似指的是拥有相同的形参列表。
2代码
abstractclassDevice { privateStringname; publicabstractdoublegetPrice(); publicDevice(){} publicDevice(Stringname) { this.name=name; } //此处省略了name的setter和getter方法 publicvoidsetName(Stringname) { this.name=name; } publicStringgetName() { returnthis.name; } } publicclassAnonymousInner { publicvoidtest(Deviced) { System.out.println("购买了一个"+d.getName() +",花掉了"+d.getPrice()); } publicstaticvoidmain(String[]args) { AnonymousInnerai=newAnonymousInner(); //调用有参数的构造器创建Device匿名实现类的对象 ai.test(newDevice("电子示波器") { publicdoublegetPrice() { return67.8; } }); //调用无参数的构造器创建Device匿名实现类的对象 Deviced=newDevice() { //初始化块 { System.out.println("匿名内部类的初始化块..."); } //实现抽象方法 publicdoublegetPrice() { return56.2; } //重写父类的实例方法 publicStringgetName() { return"键盘"; } }; ai.test(d); } }
3运行
购买了一个电子示波器,花掉了67.8
匿名内部类的初始化块...
购买了一个键盘,花掉了56.2
当创建以Device为父类的匿名内部类时,既可以传入参数,代表调用父类带参数的构造器;也可以不传入参数,代表调用父类无参数的构造器。
当创建匿名内部类时,必须实现接口或抽象父类里的所有抽象方法。如果有需要,也可以重写父类中的普通方法。
四实战
1点睛
在Java8之前,Java要求被局部内部类、匿名内部类访问的局部变量必须使用final修饰,从Java8开始这个限制取消了,Java8更加智能:如果局部变量被匿名内部类访问,那么该局部变量相对于自动使用了final修饰。
2代码
interfaceA { voidtest(); } publicclassATest { publicstaticvoidmain(String[]args) { intage=8;//① //下面代码将会导致编译错误 //由于age局部变量被匿名内部类访问了,因此age相当于被final修饰了 //age=2; Aa=newA() { publicvoidtest() { //在Java8以前下面语句将提示错误:age必须使用final修饰 //从Java8开始,匿名内部类、局部内部类允许访问非final的局部变量 System.out.println(age); } }; a.test(); } }
3结果
8
4说明
Java8将这个功能称为“effectivelyfinal”,它的意思是对于被匿名内部类访问的局部变量,可以用final修饰,也可以不用final修饰,但必须按照有final修饰的方式来使用——也就是一次赋值后,以后不能重新赋值。
更多java相关内容感兴趣的读者可查看本站专题:《Java面向对象程序设计入门与进阶教程》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总》
希望本文所述对大家java程序设计有所帮助。