Java程序设计与应用开发(第3版)
上QQ阅读APP看书,第一时间看更新

3.6 内部类

在一个类的内部我们还可以定义类,这就是内部类,也称为嵌套类。内部类的定义范围要比包小,它定义在另一个类里面,也可以定义在一个方法里面,甚至可以定义在一个表达式中。与内部类相对而言,包含内部类的类称为外部类或顶级类。

内部类本身是一个类,但它同时又是外部类的一个成员。作为外部类的成员,它可以毫无限制地访问外部类的变量和方法,包括private成员。这和private的含义并不矛盾,因为private修饰符只是限制从一个类的外部访问该类成员的权限,而内部类在外部类内部,所以它可以访问外部类的所有资源。

内部类又具有多种形式,可细分为:静态内部类、成员内部类、本地内部类和匿名内部类。在一个顶级类中声明一个类,并用static修饰符修饰的该类,就是静态内部类。例如:

     package mypackage;
     public class OuterClass {
         ...
         
         public static class StaticInnerClass {
             ...
         }
     }

该例中静态内部类的完全限定名称为mypackage.OuterClass.StaticInnerClass,编译时Java产生两个class文件:OuterClass.class和OuterClass$StaticInnerClass.class。静态内部类作为外部类的静态成员,和其他静态变量、静态方法一样,与对象无关,静态内部类只可以访问外部类的静态变量和静态方法,而不能直接引用定义在外部类中的实例变量或者方法,但可以通过对象的引用来使用它们。

匿名内部类是没有名字的内部类。由于匿名内部类没有名称,在程序中没有办法引用它们。在Java中,创建匿名内部类对象的语法如下:

     new 类或接口() {类的主体}

这种形式的new语句声明一个匿名内部类,它对一个给定的类进行扩展,或者实现一个给定的接口。它还创建匿名内部类的一个对象实例,并把这个对象实例作为new语句的返回值。在Java程序中,匿名内部类的使用十分广泛,它常被用来实现某个接口。例如实现Enumeration接口(它定义在java.util包中),Enumeration接口提供了方法,用来遍历集合数据结构的每个成员,而不暴露集合对象本身。

下面通过一个例子来说明匿名内部类的用法,该例子实现了一个简单的动态数组。

例3.16 JDynamicArray.java

     import java.util.Enumeration;
     public class JDynamicArray{
       private Object[] array = null;
       private int count = 0;
       public JDynamicArray(int size) {
         if (size <= 0) {
           throw new IllegalArgumentException("size must > 0");
         }
         array = new Object[size];
       }
       public int add(Object obj) {
         if (count == array.length) {
           Object[] newArray = new Object[array.length * 2 + 1];
           for (int i = 0; i < array.length; i++) {
             newArray[i] = array[i];
           }
           array = newArray;
         }
         array[count++] = obj;
         return count;
       }
       public Enumeration getEnumeration() {
         //匿名内部类实现Enumeration接口
         return new Enumeration() {
           private int index = 0;
           public boolean hasMoreElements() {
             return index < count;
           }
           public Object nextElement() {
             return array[index++];
           }
         };
       }
       public static void main(String[] args) {
         JDynamicArray da = new JDynamicArray(10);
         for(int i=0; i<10; i++) {
           da.add(new Integer(i));
         }
         for (Enumeration e = da.getEnumeration(); e.hasMoreElements(); ) {
           System.out.println(e.nextElement());
         }
       }
     }

程序运行结果:

     0
     1
     ...
     9