有关匿名内部类的来龙去脉
--深圳信狮职业培训学校 吴章勇
匿名内部类在java的事件处理中被广为采用,但很多人对此不甚理解,此文对匿名内部类的来龙去脉进行了研究,有助于解开大家心头的疑惑。
先看如下示例:
abstract class Parent {
abstract void f1();
void f2() {}
public static void main(String[] args) {
Parent p = null;
// p=new Parent();此步报错!因为Parent是抽象类,不能实例化。
//该如何对p进行初始化,从而使用其中的f2()方法呢?
p.f2();
}
}
代码1
要使用代码中的实例方法f2(),就必须构造一个Parent类的实例,但是Parent类又是抽象类,不能实例化,如何解决其中的矛盾?根据笔者研究,有如下四种解决方案。
一、构造抽象类Parent的外部子类OutChild,再将OutChild实例化对象赋给父类对象p即可,如下代码所示:
abstract class Parent {
abstract void f1();
void f2() {}
public static void main(String[] args) {
Parent p = null;
p = new OutChild();
p.f2();
}
}
class OutChild extends Parent {
void f1() {}
}
二、构造抽象类Parent的内部子类InnerChild,再将InnerChild实例化对象赋给父类对象p,因为要在静态方法main中使用内部子类InnerChild,所以InnerChild必须定义成static,如下代码所示:
abstract class Parent {
abstract void f1();
void f2() {}
public static void main(String[] args) {
Parent p = null;
p = new InnerChild();
p.f2();
}
static class InnerChild extends Parent {
void f1() {}
}
}
代码二
三、在main方法中构造抽象类Parent的局部子类LocalChild,再将LocalChild实例化对象赋给父类对象p即可,如下代码所示:
abstract class Parent {
abstract void fabstract ();
void f2() {}
public static void main(String[] args) {
class LocalChild extends Parent {
void f1() {}
}
Parent p = null;
p = new LocalChild();
p.f2();
}
}
代码三
以上的内部子类InnerChild和局部子类LocalChild都不是独立存在的,而是存在于父类Parent内部的内部类,相对于外部子类OutChild,内部子类InnerChild和局部子类LocalChild的优势在于可以访问父类Parent内的私有属性和方法,而外部子类OutChild做不到这一点。但是不管是外部子类OutChild,还是内部子类InnerChild或者局部子类LocalChild,都增加了类的数量,如果构造子类的目的仅仅是为了给父类对象赋值,连子类的名称也是可以省略的,所以还有如下第四种解决方案--匿名内部类。
四、匿名内部类,代码如下:
abstract class Parent {
abstract void f1();
void f2() {}
public static void main(String[] args) {
Parent p = null;
p = new Parent() {
void f1() {
}
};
p.f2();
}
}
代码四
以上代码中
p = new Parent() {
void f1() {
}
};
即是匿名内部类,这里并不是在对Parent进行实例化(Parent是抽象类,也不能实例化),而是对Parent的未命名子类进行实例化,并在Parent的未命名子类中,对父类Parent中的抽象方法f1()进行了实现,这就是匿名内部类!匿名内部类同样享有可以访问父类Parent内的私有属性和方法的优势,并减少了类的设计,所在在java的事件处理中被广为采用。