ThinkingInJava----第10章 内部类

内部类:
外部类与内部类的private 元素可以相互访问。
内部类看成外部类的一个对象来访问。

方法中创建内部类
方法的某个作用域中创建内部类
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10.6 匿名内部类
1.在匿名内部类末尾是分号,是标志表达式的结束,而并不是内部类的结束,恰好表达式的结束。
2.在匿名内部类中不可能有,有名的构造器,但是通过实例初始化,能达到为匿名内部类创建构造器的效果。
(实例初始化的效果就是构造器而且你不能重载实例初始化方法)
3.匿名内部类不能即扩展类又实现接口。(如果实现接口也只能实现一个)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10.6.1 再访工厂方法
public class Outer {
    private int i;
    private void g(){
        System.out.println("g()");
    }

    public void f(){
        //匿名内部类
        new Object(){
            private void h(){
                for (;i < 3;i++)
                    System.out.println("i = " + i);
            }
        }.h();
        System.out.println("f()");
    }

    public static void main(String[] args) {
        // 创建匿名内部类的对象并且调用它的方法
        test11_2.Outer outer = new Outer();
        outer.f();
    }
}

public class test.Test {
    public test.SimplyInterface get(){
       return new test13.SimplyInterface(){
            // 不用 implements ,直接把接口的方法写进匿名内部类
            @Override
            public void f() {
                System.out.println("f()");
            }
        };
    }

    public static void main(String[] args) {
        test.Test test = new test13.Test();
        test.get().f();
    }
}

public interface test.SimplyInterface {
    void f();
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10.7 嵌套类(它的类类似与一个static 方法)
1.不需要内部类对象与其外围类对象之间又联系,那么可以将内部类声明为static,这样的类常称为嵌套类。
2.普通内部类对象隐式的保存一个对外部类的引用,
嵌套类:要创建嵌套类的对象,不需要外围类对象。
不能从嵌套内部类中访问非静态的外围类对象。
普通内部类:其字段与方法,只能放在类外部的层次上,所以普通内部类不能有static数据和static字段,也不能包含嵌套类。
但嵌套类可以包含所有这些东西。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public class Test {

    // 注意二者访问方式的不同
    public static void main(String[] args) {
        // 注意编译生成的.class文件的名字
        new Nested1().f();
        new Nested1.Nested2().g();

        Test t = new Test();
        Test.Nested1 nd1 = new Nested1();
        nd1.f();
        Test.Nested1.Nested2 nd2 = new Nested1.Nested2();
        nd2.g();
    }


    // 嵌套类
    static class Nested1{
        static class Nested2{
            void g(){
                System.out.println("Test.Nested1.Nested2.g()");
            }
        }
        void f(){
            System.out.println("Test.Nested1.f()");
        }
    }

    // 普通内部类
    class Inner1{
        class Inner2{
            public void g(){
                System.out.println("Test.Inner.Inner2.g()");
            }
        }
        public Inner2 getInner2(){
            return new Inner2();
        }
        public void f(){
            System.out.println("Test.Inner.f()");
        }
    }
    public Inner1 getInner1(){
        return new Inner1();
    }
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10.7.1 接口内部的类
1.正常情况下接口内部是不可以放代码,但嵌套类可以作为借口的一部分,放在接口中的任何类都自动的是public和static的,
因为类是static的,只是将嵌套类置于接口的命名空间内,并不违反接口的规则。
创建某些公共代码,使得他们可以被某个接口的所有不同实现所共用。

  public interface NestedInterface {
       class Nested{
          public void f(){
              System.out.println("NestedInterface.ClassB.f()");
          }
      }
  }
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public interface I {
    void g();
    void f();
    class Nested{
        static void call(I impl){
            System.out.println("I.g()");
            impl.g();
            System.out.println("I.f()");
            impl.f();
        }
    }
}
public class Test {
    public static void main(String[] args) {
        I impl = new I(){
            public void g(){}
            public void f(){}
        };
    I.Nested.call(impl);
    }
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10.7.2 从多层嵌套类中访问外部类得成员

1.一个内部类被嵌套多少层并不重要,只要它能透明的访问所有它所嵌入的外围类的所有成员。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10.8 为什么需要内部类
1.内部类提供了某种进入外部类的窗口。
2.每个内部类都能都能独立的继承一个接口的实现,所以一个外部类是否实现了某个接口,对内部类并无影响。
3.内部类实现了“多重继承”
4.内部类还可以获得一些其它的特征
1)可以有多个实例,每个实例都有自己的状态信息,并且与外部对象的信息相互独立,
2)单个外部类,可以让多个内部类以不同的方式实现一个接口,或继承同一个类。
3)创建内部类对象的时刻,不依赖外围类对象的创建。
4)内部类就是一个独立的实体,没有is-a关系
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10.8.1 闭包与回调
1.闭包(closure) 是一个可调用的对象,它记录了对象的信息,这些信息源来自于创建它的作用域。
可以看出内部类是面向对象的闭包,因为它不仅包含外围类对象的信息,还自动拥有一个指向一个此外围类对象的引用。
(在此作用域内部类包含所有成员的操作权限包括private)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10.8.2 内部类控制框架
1.内部类用来解决问题所需的各种action()
2.内部类很容易访问外围类的任意成员。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10.9 内部类的继承
public class OuterTwo {

    // 报错
    /*class InnerTwo extends OuterOne.InnerOne{
        public InnerTwo(int i) {
            super(i);
        }
    }*/

    class InnerTwo extends OuterOne.InnerOne{
        public InnerTwo(OuterOne oo,int i) {
            oo.super(i);
        }
        public void f(){
            System.out.println("OuterTwo.InnerTwo.f(0");
            super.f();
        }
    }

    public static void main(String[] args) {
        OuterOne oo = new OuterOne();
        OuterTwo ot = new OuterTwo();
        OuterTwo.InnerTwo it = ot.new InnerTwo(oo,47);
        it.f();

    }
}
public class OuterOne {

    class InnerOne{
        private int i = 1;
        public InnerOne(int i){
            System.out.println("OuterOne.InnerOne");
        }
        public void f(){
            System.out.println("Outer.InnerOne.f()");
        }
    }
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10.10 内部类可以被覆盖吗?
覆盖内部类就好像是一个外围类的方法,其实并不起什么作用。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10.11 局部内部类
典型的方式是在一个方法体中创建,局部内部类是不能有访问说明符的,因为它不是外围类的一部分,
但它可以访问当前代码块内部的常量以及所有成员。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10.12 内部类标识符
$,产生的文件都是自动与平台无关。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
总结
什么情况下用接口,什么情况下用内部类

posted @ 2017-03-28 12:44  lifehrx  阅读(168)  评论(0编辑  收藏  举报