看《JAVA编程思想》这本书,已经看了×××个月了,才看到第10章,万分汗颜!惰性真的可怕!

    可以将一个类的定义放在另一个类的定义内部,这就是内部类

    当生成一个内部类的对象时,此对象与制造它的外围对象之就有了一种联系,所以它能访问其外围对象的所有成员,而不需要任何特殊条件。此外,内部类还拥有其外围类的所有元素的访问权。

    当某个外围类的对象创建了一个内部类对象时,此内部类对象必定会秘密地捕获一个指向那个外围类对象的引用。然后,在你访问此外围类的成员时,就是用那个引用来选择外围类的成员。内部类的对象只能在与其外围类的对象相关联的情况下才能被创建(就像你应该看到的,在内部类是非static类时)

    

使用.this和.new

    如果你需要生成对外部类对象的引用,可以使用外部类的名字后面紧跟圆点和this。这样产生的引用自动地具有正确的类型,这一点在编译期就被知晓并受到检查,因此没有任何运行时开销。


    有时你可能想要告知某些其它对象,去创建其某个内部类的对象。要实现此目的,你必须在new表达式中提供对其它外部类对象的引用,这是需要使用.new语法。例:

    public class DotNew {

        public class Inner {}

        public static void main(String[] args) {

            DotNew dn = new DotNew();

            DotNew.Inner dni = dn.new Inner();

        }

    }

    在拥有外部类对象之前是不可能创建内部类对象的,而必须使用外部类的对象来创建该内部类对象。这是因为内部类对象会暗暗地连接到创建它的外部类对象上。 但是,如果你创建的是嵌套类(静态内部类),那么它就不需要对外部类对象的引用。

        

在方法和作用域内的内部类

    可以在一个方法内或任意作用域内定义内部类。

    这样做用由两个理由

    (1) 如前所示,你实现了某类型的接口,于是可以创建并返回对其的引用。

    (2)你要解决一个复杂的问题,想创建一个类来辅助你的解决方案,但是又不希望这个类是公共可用的

    例:

    interface I {}

    class A {

        public  I  getB() {

            class B implements I {}

            return new B();

        }

    }


匿名内部类

    如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,那么编译会要求其参数引用是final的。

    

嵌套类

    如果不需要内部类对象与其外围类对象之间有联系,那么可以讲内部类声明为static。这通常称为嵌套类。

    普通的内部类对象隐式地保存了一个引用,指向创建它的外围类对象。然而,当内部类是static的时,就不是这样了。嵌套类意味着:

    1)要创建嵌套类的对象,并不需要其外围类的对象

    2)不能从嵌套类的对象中访问非静态的外围类对象

    嵌套类与普通的内部类还有一个区别。普通内部类的字段与方法,只能放在类的外部层次上,所以普通的内部类不能有static数据和static字段,也不能包含嵌套类。但是嵌套类可以包含所有这些东西

    


闭包与回调

    闭包(closure) 是一个可调用的对象,它记录了一些信息,这些信息来自于创建它的作用域。通过这个定义,可以看出内部类是面相对象的闭包,因为它不不仅包含外围类对象(创建内部类的作用域)的信息,还自动拥有一个指向此外围类对象的引用,在此作用域内,内部类有权操作所有的成员,包括private成员



内部类继承

    因为内部类的构造器必须连接到指向其外围类对象的引用,所以在继承内部类的时候,事情会变得有点复杂。问题在于,那个指向外围类对象的"秘密的" 引用必须被初始化,而在导出类中不再存在可连续的默认对象。要解决这个问题,必须使用特殊的语法来明确说明它们之间的关系

    

局部内部类

    局部内部类不能有访问说明符,因为它不是外围类的一部分;但是它可以访问当前代码块内的常量,以及此外围类的所有成员。


内部类标识

    java的每个类都会生成一个.class文件。内部类命名的规则为:外围类的名字,加上 "$",再加上内部类的名字。如果内部类是匿名的,编译器会简单地生成一个数字作为其标识符。如果内部类是嵌套在别的内部类之中,只需要将他们的名字加在其外围类标识符与 "$" 的后面。