06_匿名内部类
【匿名内部类】
匿名内部类适合创建只需要一次使用的类。创建匿名内部类时会立即创建一个该类的实例,这个类的定义立即消失,匿名内部类不能重复使用。
【定义匿名内部类的格式】
new 实例接口() | 父类构造器(实参列表) { //匿名内部类的类体部分 }
从定义中可见,匿名内部类必须继承一个父类,或实现一个接口,但最多也只能实现一个接口或继承一个父类。
【匿名内部类的两条规则】
1.匿名内部类不能是抽象类。
[ 原因 ]因为系统在创建匿名内部类的时候,会立即创建匿名内部类的对象。
2.匿名内部类不能定义构造方法。
[ 原因 ]由于匿名内部类没有类名,所以无法定义构造方法,但是匿名内部类可以定义初始化块,可以通过实例初始化块来完成构方法需要完成的事情。
【实例】
package com.Higgin.anonymous; interface Product{ public double getPrice(); public String getName(); } class AnonyMousDemo{ public void printNameAndPrice(Product p){ System.out.println(p.getName()+"------"+p.getPrice()); } } public class AnonyMousTest { public static void main(String[] args) { AnonyMousDemo amd=new AnonyMousDemo(); /** * 此处调用AnonyMousDemo的printNameAndPrice(p)方法。 * 传入其匿名内部类的实例,定义匿名内部类无需class关键字,直接生产该匿名内部类的对象
* 通过实现接口来创建匿名内部类时,匿名内部类无法显式创建构造方法,匿名内部类只有一个隐式的无参构造方法 */ amd.printNameAndPrice(new Product(){ @Override public double getPrice(){ //匿名内部类中必须实现他的 抽象父类或接口中 所有的抽象方法! return 998.8; } @Override public String getName() { return "战斗机手机"; } }); } }
【运行结果】
【分析】
AnonyMousDemo类的printNameAndPrice(Product p)方法需要传入一个Product的对象作为参数,但是Product是一个接口,无法直接创建对象,因此此处考虑的是创建一个Product接口的实现类的对象作为参数传入。(注意:如果这个Product接口的实现类只需使用一次,可以采用本例的方式;如果是Product的实现类需要多次使用,应该将该实现类定义成一个独立的类,方便多次使用)。
【区分单独定义情况(和上面作对比用)】
package com.Higgin.anonymous; interface Product{ public double getPrice(); public String getName(); } class ProductPhone implements Product{ @Override public double getPrice(){ return 998.8; } @Override public String getName() { return "战斗机手机"; } } class AnonyMousDemo{ public void printNameAndPrice(Product p){ System.out.println(p.getName()+"------"+p.getPrice()); } } public class AnonyMousTest { public static void main(String[] args) { AnonyMousDemo amd=new AnonyMousDemo(); /** * 这里直接传入Product接口的实现类ProductPhone的对象 */ amd.printNameAndPrice(new ProductPhone()); } }
【对比结论】
采用匿名内部类明显会简洁一些。
当通过实现接口来创建匿名内部类的时候,匿名内部类也不能显式创建构造方法,因此匿名内部类只能有一个隐式的构造方法,故"new 接口名()"的括号中不能传入参数值。
【如果通过继承父类来创建匿名内部类,匿名内部类将拥有和父类相似的构造器】
package com.Higgin.anonymous; /** * 抽象类Product(之前例子是接口) */ abstract class Product{ private String name; public abstract double getPrice(); public Product(){} //无参构造方法 public Product(String name ){ //有参构造方法 this.name=name; } //name的get方法 public String getName() { return name; } } class AnonyMousDemo{ public void printNameAndPrice(Product p){ System.out.println(p.getName()+"------"+p.getPrice()); } } public class AnonyMousTest { public static void main(String[] args) { AnonyMousDemo amd=new AnonyMousDemo(); /** * 调用 有参构造方法,创建Product匿名实现类的对象 */ amd.printNameAndPrice(new Product("手机中的战斗机"){ @Override public double getPrice() { //实现其抽象方法 return 998.8; } }); System.out.println("---------------------我是飘过的分割线----------------------------"); /** * 调用无参的构造方法,创建Product匿名实现类的对象 */ Product product=new Product(){ //初始化块 { System.out.println("===匿名内部类的初始化块==="); } @Override public double getPrice() { //实现其抽象方法 return 889.9; } public String getName(){ //重写父类的实例方法getName return "手机中的轰炸机"; } }; amd.printNameAndPrice(product); } }
【运行结果】
【小结】
创建匿名内部类时,必须实现 接口或者抽象父类里的抽象方法,如果有需要也可以重写 父类中的普通方法。