Java面试问题之二十八
请阅读以下代码段,给出这段程序运行结果,并尝试总结一下匿名类的特点。
package com.ecom.baidu;
public class A {
A(int v) {
System.out.println("another constructor");
}
A() {
System.out.println("default constructor");
}
void method() {
System.out.println("from A");
}
public static void main(String[] args) {
new A().method();
A a = new A() {
void method() {
System.out.println("from anonymous");
}
};
a.method();
}
}
问题分析:这段代码很明显就是在考察Java匿名类的使用,所谓匿名类就是一种特殊的内部类,这种类没有名字。以上代码段中“new A(){...}”定义了一个
继承类A的匿名类,大括号内是类A的类体,“new A(){...}”返回匿名类的一个实例的引用。其中,“ A a = new A(){...}”语句等价于以下代码:
class SubA extends A {
void method() {System.out.println("from anonymous");}
}
A a = new SubA(); //创建局部内部类
因此,上述代码段运行结果是:
default constructor
from A
default constructor
from anonymous
匿名类作为Java的一种特殊的类类型,它具有以下几个特点:
(1)匿名类本身是没有构造方法的,但是它会调用父类的构造方法。
(2)匿名类尽管没有构造方法,但是可以在匿名类中提供一段实例初始化代码,Java虚拟机会在调用了父类的构造方法后,执行这段代码。
(3)除了可以在外部类的方法内定义匿名类之外,还可以在声明一个成员变量时定义匿名类。
(4)匿名类除了可以继承外,还可以实现接口。例如:
class Sample {
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
public void run() {
for(int i=0;i<100;i++)
System.out.println(i);
}
});
t.start();
}
}
以上匿名类实现了java.lang.Runnable接口,把这个匿名类的实例的引用作为参数,传给java.lang.Thread类的构造方法。
(5)匿名类和局部内部类一样,可以访问外部类的所有成员,如果匿名类位于一个方法中,还能访问所在方法的final类型的变量和参数。
(6)局部内部类的名字在方法外是不可见的,因此与匿名类一样,能够起到封装类型名字的作用。局部内部类与匿名类的区别在于:
* 匿名类的程序代码一般相对简短。
* 一个局部内部类可以有多个重载构造方法,并且客户类可以多次创建局部内部类的实例。
而匿名类由于没有重载方法,并且只能创建一次性实例。
因此,如果只需要创建内部类的一个实例,可以使用匿名类,它能够使程序比较简洁;但是,如果需要多次创建内部类的实例则必须使用局部内部类。