日期:2014-05-20  浏览次数:20776 次

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)局部内部类的名字在方法外是不可见的,因此与匿名类一样,能够起到封装类型名字的作用。局部内部类与匿名类的区别在于:

* 匿名类的程序代码一般相对简短。
* 一个局部内部类可以有多个重载构造方法,并且客户类可以多次创建局部内部类的实例。
    而匿名类由于没有重载方法,并且只能创建一次性实例。
因此,如果只需要创建内部类的一个实例,可以使用匿名类,它能够使程序比较简洁;但是,如果需要多次创建内部类的实例则必须使用局部内部类。