简单,可复制

点点滴滴,尽在文中

  :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

原文出自 http://www.cnblogs.com/ggjucheng/archive/2012/12/01/2797685.html

英文出自 http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

java程序语言允许你在一个类里面再声明另一个类,这样的类成为嵌套类,说明如下:

class OuterClass {
    ...
    class NestedClass {
        ...
    }
}

术语:嵌套类分为两种:静态或非静态。嵌套类声明为static称为静态嵌套类。非静态嵌套类都称为内部类。

class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}

一个嵌套类是它的封装类的成员。非静态嵌套类可以访问它的封装类的其他成员,即使这些成员声明是private。静态嵌套类不能访问封装类的其他成员。就像外部类的一个成员一样,嵌套类可以声明为private,public,protected,包内私有(回顾外部类只能声明为public或者是包内私有)

 

为什么使用嵌套类

使用嵌套类,其中有几个令人信服的理由:

  • 它是一个在一个地方使用类的逻辑分组的方法
  • 它加强封装
  • 嵌套类可以促进更可读性,可维护性的代码。

类的逻辑分组—如果一个类只是被其他一个类使用,那么合乎逻辑的是把它嵌套到该类,让这两个类在一起。嵌套这样的帮助类可以让包更加精简。

加强封装—考虑两个顶级类,A和B,如果B需要访问A的private成员,通过在A类隐藏B类,那么即使A的成员声明为private,那么B也可以访问它们。更多的是,B本身也可以隐藏于外部。

更可读性,可维护性的代码—在顶级类里嵌套小类,让代码更靠近使用的地方。

 

 

静态嵌套类

和类方法,类变量一样,一个静态嵌套类是和它的外部类关联的。就像静态类方法一样,一个静态嵌套类不能直接引用封装类的实例变量或者方法—它只能通过封装类的引用访问它们。

注意:一个静态嵌套类访问它的封装类(和其他类)的实例成员,就像访问其他顶级类一样。事实上,一个静态嵌套类就像一个顶级类,只是行为上嵌套在另一个顶级类里而已,达到打包方便的目的。

静态嵌套类是使用封装类的名字访问:

OuterClass.StaticNestedClass

例如,创建一个静态嵌套类的对象,语法是:

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

 

内部类

如实例方法和实例字段一样,一个内部类是和封装类的实例关联的,并且可以直接访问这个对象的成员和方法。正是因为一个内部类是和实例关联的,所以它不能定义任何静态成员。

内部类的对象实例存在于外部类的实例,考虑下面的类:

class OuterClass {
    ...
    class InnerClass {
        ...
    }
}

一个内部类的实例,尽可以存在于外部类的实例中,并且可以直接访问封装实例的方法和字段。下图说明了这个想法:

 

An Instance of InnerClass Exists Within an Instance of OuterClass.

 

一个内部类的实例存在于外部类的实例

实例化内部类之前,你首先要实例化外部类。然后基于外部类的对象创建内部类对象,语法是:

还有,有两种特别的内部类,局部类和匿名类(也可以成为匿名内部类)。这两者会在后面讨论。

 

内部类例子

为了演示内部类的使用,让我们思考一个数组。接下来的例子,我们会创建一个数组,填充为整数,输出的数组的索引值是升序的。

下面的DataStructure类包括:

  • DataStructure外部类,包含了添加整数到内部数组的方法,输出数组里的索引值
  • InnerEvenIterator内部类,类似java的标准迭代器。迭代器用于遍历一个数据结果,典型的是判断是否到了最后一个元素,检索当前元素,移动到下一个元素。
  • 在main方法里实例化DataStructure对象,使用它填充数组arrayOfInts为一系列整数(0, 1, 2, 3, etc.),然后调用一个printEven 方法,输出arrayOfInts的索引值。
public class DataStructure {
    // create an array
    private final static int SIZE = 15;
    private int[] arrayOfInts = new int[SIZE];
    
    public DataStructure() {
        // fill the array with ascending integer values
        for (int i = 0; i < SIZE; i++) {
            arrayOfInts[i] = i;
        }
    }
    
    public void printEven() {
        // print out values of even indices of the array
        InnerEvenIterator iterator = this.new InnerEvenIterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.getNext() + " ");
        }
    }
    
    // inner class implements the Iterator pattern
    private class InnerEvenIterator {
        // start stepping through the array from the beginning
        private int next = 0;
        
        public boolean hasNext() {
            // check if a current element is the last in the array
            return (next <= SIZE - 1);
        }
        
        public int getNext() {
            // record a value of an even index of the array
            int retValue = arrayOfInts[next];
            //get the next even element
            next += 2;
            return retValue;
        }
    }
    
    public static void main(String s[]) {
        // fill the array with integer values and print out only
        // values of even indices
        DataStructure ds = new DataStructure();
        ds.printEven();
    }
}

输出是:

0 2 4 6 8 10 12 14 

注意InnerEvenIterator是直接引用DataStructure对象的实例变量arrayOfInts。

内部类可用来实现帮助类,就像上面的例子。如果你计划处理用户接口事件,你需要指导如何使用内部类,因为事件处理机制中,内部类是广泛使用的。

 

局部和匿名内部类

有两种良性的内部类。你可以在方法体内声明一个内部类。这样的类成为局部内部类。你也可以在方法体内,声明一个没有名字的内部类,这种类就是匿名内部类了。我们将会在java高级编程遇到它。

 

修饰符

可以为内部类使用修饰符,就像外部类成员那么使用。例如,可以使用特殊访问—private,public,protected—限制访问内部类的方式,就像和其他类成员的使用方式一样。

posted on 2012-12-01 21:44  ggjucheng  阅读(2245)  评论(0编辑  收藏  举报