上面就是这样一个例子。在方法dest中我们定义了一个内部类,最后由这个方法返回这个内部类的对象。如果我们在用一个内部类的时候仅需要创建它的一个对象并创给外部,就可以这样做。当然,定义在方法中的内部类可以使设计多样化,用途绝不仅仅在这一点。
下面有一个更怪的例子:
public class Goods2{ private void internalTracking(boolean b) { if(b) { class TrackingSlip { private String id; TrackingSlip(String s) { id = s; } String getSlip() { return id; } } TrackingSlip ts = new TrackingSlip("slip"); String s = ts.getSlip(); } } public void track() { internalTracking(true); } public static void main(String[] args) { Goods2 g= new Goods2(); g.track(); } } |
你不能在 if 之外创建这个内部类的对象,因为这已经超出了它的作用域。不过在编译的时候,内部类 TrackingSlip 和其他类一样同时被编译,只不过它由它自己的作用域,超出了这个范围就无效,除此之外它和其他内部类并没有区别。
2.匿名类
匿名类是不能有名称的类,所以没办法引用他们。必须在创建时,作为new语句的一部分来声明他们。
这就要采用另一种形式的new语句,如下所示:
new <类或接口> <类的主体>
这种形式的new语句声明一个新的匿名类,他对一个给定的类进行扩展,或实现一个给定的接口。他还创建那个类的一个新实例,并把他作为语句的结果而返回。要扩展的类和要实现的接口是new语句的操作数,后跟匿名类的主体。
假如匿名类对另一个类进行扩展,他的主体能够访问类的成员、覆盖他的方法等等,这和其他任何标准的类都是相同的。假如匿名类实现了一个接口,他的主体必须实现接口的方法。
注意匿名类的声明是在编译时进行的,实例化在运行时进行。这意味着for循环中的一个new语句会创建相同匿名类的几个实例,而不是创建几个不同匿名类的一个实例。
从技术上说,匿名类可被视为非静态的内部类,所以他们具备和方法内部声明的非静态内部类相同的权限和限制。
假如要执行的任务需要一个对象,但却不值得创建全新的对象(原因可能是所需的类过于简单,或是由于他只在一个方法内部使用),匿名类就显得很有用。匿名类尤其适合在Swing应用程式中快速创建事件处理程式。
interface pr { void print1(); } public class noNameClass { public pr dest() { return new pr() { public void print1() { System.out.println("Hello world!!"); } }; } } public static void main(String args[]) { noNameClass c = new noNameClass(); pr hw = c.dest(); hw.print1(); } |
pr 也可以是一个类,但是你外部调用的方法必须在你的这个类或接口中声明,外部不能调用匿名类内部的方法。
Java 中内部匿名类用的最多的地方也许就是在 Frame 中加入 Listner 了吧。
import java.awt.*; import java.awt.event.*; public class QFrame extends Frame { public QFrame() { this.setTitle(\"my application\"); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { dispose(); System.exit(0); } }); this.setBounds(10,10,200,200); } } |
内部匿名类,就是建立一个内部的类,但没有给你命名,也就是没有引用实例的变量。
new WindowAdapter() { public void windowClosing(WindowEvent e) { dispose(); System.exit(0); } } |
new 是建立一个 WindowAdapter 对象,后面一个 {} 表示这个括号中的操作作用于这个默认的对名象,而上面的 Java 程序中后面是一个函数体。
这个用法的作用是:创建一个对象的实例,并且 override 它的一个函数。
打开 WindowAdapter 的代码可以发现。它是一个抽象类。它是对 WindowListener 接口的一个实现。
Frame.addWindowListner(); 的参数是一个 WindowListner ,而实现上是传一个从WindowAdapter 派生出的一个匿名类。
有一点需要注意的是,匿名内部类由于没有名字,所以它没有构造函数(但是如果这个匿名内部类继承了一个只含有带参数构造函数的父类,创建它的时候必须带上这些参数,并在实现的过程中使用 super 关键字调用相应的内容)。如果你想要初始化它的成员变量,有下面几种方法:
1. 如果是在一个方法的匿名内部类,可以利用这个方法传进你想要的参数,不过记住,这些参数必须被声明为 final 。
2. 将匿名内部类改造成有名字的局部内部类,这样它就可以拥有构造函数了。
3. 在这个匿名内部类中使用初始化代码块。