语法:
new 类或接口(参数列表){ //匿名内部类代码 }
定义位置:定义在类的局部位置,即类的方法或代码块中。
原理:用类来实现接口
public class AnonymousInnerClass { public static void main(String[] args) { //测试匿名内部类 Outer04 outer04 = new Outer04(); outer04.method(); } }
interface A_ { void cry(); }
class Outer04 { private int n1 = 10; public void method(){ //new A_(){}会创建一个匿名内部类实现接口A_,并创建该内部类的实例对象 //编译类型接口A_,运行类型为匿名内部类 A_ tiger = new A_(){ private int n1 = 100; @Override public void cry() { System.out.println("老虎在叫唤..."); System.out.println("n1=" + n1); //就近原则,访问内部类属性 System.out.println("Outer04.this.n1=" + Outer04.this.n1); //外部类名.this.外部类成员名 可以访问外部类的所有成员 } }; System.out.println("tiger的运行类型为 " + tiger.getClass()); tiger.cry(); //动态绑定机制,运行时多态,接口多态 }
代码解读:使用javap可以查看编译后的源代码
(1)底层会为该内部类分配类名Outer04$1,并实现接口A_ class Outer04$1 implements A_{ @Override public void cry(){ System.out.println("老虎在叫唤..."); } } (2)JDK底层在创建内部类Outer04$1之后,new立即创建了该类的实例对象,并把对象的地址返回给变量tiger; (3)匿名内部类使用一次,就不能再使用了,如果想继续使用,需要再实现。
原理:使用类的继承机制
class Father { public Father(String name) { } public void test(){ } }
class Outer04 { public void method(){ //编译类型Father,运行类型Outer04$2 Father father = new Father("pony") { @Override public void test() { System.out.println("匿名内部类重写了test方法"); } }; System.out.println("father的运行类型为 " + father.getClass()); father.test(); //动态绑定,运行时多态 } }
代码解读:
(1)类之间的关系,采用继承实现,底层会创建内部类Outer04$2,并继承Father class Outer04$2 extends Father { ... } (2)创建好内部类之后,用关键字new创建该内部类的实例对象,并将对象的地址返回给变量father。
public class InnerClassExercise01 { public static void main(String[] args) { //经典使用场景1:匿名内部类创建的对象直接作为实参传递,尤其是该对象只使用一次时,灵活简洁 //基于接口的匿名内部类 test(new Picture() { @Override public void show() { System.out.println("千里江山图"); } }); test(new Picture() { @Override public void show() { System.out.println("清明上河图"); } }); } public static void test(Picture picture){ //形参类型为接口类型,实现多态 picture.show(); } } interface Picture{ void show(); }