zoukankan      html  css  js  c++  java
  • Thinking in java Chapter10 内部类

    内部类:一个类的定义放在另一个类的定义内部

    • 逻辑相关的类组织在一起,并控制位于内部的类的可视性。
    • 与组合是完全不同的概念。

    10.1 创建内部类

    // 创建内部类
    public class Parcel1 {
        class Contents{
            private int i = 11;
            public int value(){ return i;}
        }
        class Destination{
            private String label;
            Destination(String whereTo){ label = whereTo;}
            String readLable(){ return label;}
        }
        // Using inner classes looks just like using any other class. within Parcel1:
        public void ship(String dest){ // 使用内部类
            Contents c = new Contents();
            Destination d = new Destination(dest);
            System.out.println(d.readLable());
        }
    
        public static void main(String[] args) {
            Parcel1 p = new Parcel1();
            p.ship("Tasmania");
        }
    }
    
    
    // 返回一个指向内部类的引用
    public class Parcel2 {
        class Contents{
            private int i = 11;
            public int value(){ return i;}
        }
        class Destination{
            private String label;
            Destination(String whereTo){ label= whereTo;}
            String readLabel(){return label;}
        }
        public Destination to(String s){
            return new Destination(s);
        }
        public Contents contents(){
            return new Contents();
        }
        public void ship(String dest){
            Contents c = contents();
            Destination d = to(dest);
            System.out.println(d.readLabel());
        }
    
        public static void main(String[] args) {
            Parcel2 p = new Parcel2();
            p.ship("Tasmania");
            Parcel2 q= new Parcel2();
            Parcel2.Contents c = q.contents(); // 创建内部类对象 outerClassName.InnerClassName
            Parcel2.Destination d = q.to("Borneo");
    
        }
    }
    
    

    10.2 创建到外部类

    内部类对象拥有一个对外围类对象的引用

    package chapter10Innerclasses;
    //
    
    interface Selector{ // 迭代器模式
        boolean end();
        Object current();
        void next();
    }
    
    public class Sequence {
        private Object[] items;
        private int next = 0;
        public Sequence(int size) {items = new Object[size];}
        public void add(Object x){
            if(next < items.length)
                items[next++] = x;
        }
        private class SequenceSelector implements Selector {
            private int i = 0;
    
            @Override
            public boolean end() {
                return i == items.length;
            }
    
            @Override
            public Object current() {
                return items[i];
            }
    
            @Override
            public void next() {
                if (i < items.length) i++;
    
            }
        }
    
        public Selector selector(){
            return new SequenceSelector();
        }
    
        public static void main(String[] args) {
            Sequence sequence = new Sequence(10);
            for (int i = 0;i < 10;i++)
                sequence.add(Integer.toString(i));
            Selector selector = sequence.selector();
            while (!selector.end()){
                System.out.println(selector.current() + " ");
                selector.next();
        }
        }
    }
    
    

    10.3 使用.this与.new

    package chapter10Innerclasses;
    
    public class DotThis {
        void f(){
            System.out.println("DotThis.f()");
        }
        public class Inner{
            public DotThis outer(){
                return DotThis.this; // 外部类.this  外围类引用
            }
        }
        public Inner inner(){
            return new Inner();
        }
    
        public static void main(String[] args) {
            DotThis dt = new DotThis();
            DotThis.Inner dti = dt.inner();
            dti.outer().f();
        }
    }/* Output
    DotThis.f()
    */
    
    
    public class DotNew {
        public class Inner{}
    
        public static void main(String[] args) {
            DotNew dn = new DotNew();
            DotNew.Inner dni = dn.new Inner(); // 创建某个内部类的对象  不能用外部类名称如DotNew,而是用外部类的对象创建
        }
    }
    
    package chapter10Innerclasses;
    
    public class Parcel3 {
        class Contents{
            private int i =11;
            public int value(){
                return i;
            }
        }
        class Destination{
            private String label;
            Destination(String whereTo){label = whereTo;}
            String readLabel(){return label;}
        }
    
        public static void main(String[] args) {
            Parcel3 p = new Parcel3();
            Parcel3.Contents c = p.new Contents();
            Parcel3.Destination d = p.new Destination("Tasmania"); // 内部类对象会 暗暗的连接到创建它到外部类对象上。
            // 如果创建到是嵌套类(静态内部类),就不需要对外部类对象对引用。这句话没有例子
        }
    }
    
    

    10.4 内部类与向上转型

    package chapter10Innerclasses;
    
    class Parcle4{
        private class PContents implements Contents{
            private int i = 11;
            public int value(){return i;}
        }
    
        protected class PDestination implements Destination{
            private String label;
            private PDestination(String whereTO){
                label = whereTO;
            }
            @Override
            public String readlabel() {
                return label;
            }
        }
        public Destination destination(String s){
            return new PDestination(s);
        }
        public Contents contents(){
            return new PContents();
        }
    }
    public class TestParcel {
        public static void main(String[] args) {
            Parcle4 p = new Parcle4();
            Contents c = p.contents();  // 向上转型
            Destination d = p.destination("Tasmania");
    //        Parcle4.PContents pc = p.new PContents(); // 不能访问私有类 不能向下转型
        }
    }
    
    package chapter10Innerclasses.e6.package1;
    
    public interface Interface01 {
        void f();
    }
    
    package chapter10Innerclasses.e6.package2;
    
    import chapter10Innerclasses.e6.package1.Interface01;
    
    public class Class2 {
        protected class Inner implements Interface01{
    
            @Override
            public void f() {
                System.out.println("class2.inner.method()");
            }
    
            public Inner(){}  // Inner 为 protected,强制 构造函数为public
        }
    }
    
    package chapter10Innerclasses.e6.package3;
    
    import chapter10Innerclasses.e6.package1.Interface01;
    import chapter10Innerclasses.e6.package2.Class2;
    
    public class Class3 extends Class2 {
        public Interface01 get(){
            return new Inner();  // 构造函数为public 才能new
        }
    
        public static void main(String[] args) {
            new Class3().get().f();
    
        }
    
    }
    
    
    package chapter10Innerclasses.e7;
    
    public class ClassA {
        private int i = 10;
        private void methodA(){
            System.out.println("ClassA private methodA(),and i = " + i);
        }
        class Inner{
            void methodB(){
                i++;
                methodA(); // 内部类可以访问 外围类的私有字段和私有方法
                System.out.println("ClassA Inner methodB(),and i = " + i);
    
            }
        }
    
        public void methodC(){
            Inner inner =  new Inner();
            inner.methodB();
            System.out.println("methodC and i = " + i);
        }
    
        public static void main(String[] args) {
            ClassA classA = new ClassA();
            classA.methodC();
        }
    }
    

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

    内部类作用

    • 实现某类型的接口,可以创建并返回对其对引用
    • 解决复杂问题,创建一个类辅助解决,不希望它公共可用
    1. 局部内部类:方法中的类

    package chapter10Innerclasses;
    
    public class Parcel5 {
        public Destination destination(String s){
            class PDestination implements Destination{ // 方法中的类
                private String label;
                private PDestination(String whereTo){
                    label = whereTo;
                }
    
                @Override
                public String readLabel() {
                    return label;
                }
            }
            return new PDestination(s); // 返回的是 Destination 的引用
        }
    
    
        public static void main(String[] args) {
            Parcel5 p = new Parcel5();
            Destination d = p.destination("Tasmania"); // Destination 向上转型
            System.out.println(d.readLabel());
        }
    }
    
    1. 作用域中嵌入内部类

    package chapter10Innerclasses;
    // 作用域内嵌入一个内部类
    public class Parcel6 {
        private void interalTracking(boolean b){
            if (b){
                class TrackingSlip{ // 跟踪单  嵌入在if作用域中,并不是说该类创建是有条件的。它其实是与别的类一起编译的。 超出作用域外,不可用。除此之外,与普通类一样。
                    private String id;
                    TrackingSlip(String s){
                        id = s;
                    }
                    String getSlip(){
                        return id;
                    }
                }
                TrackingSlip ts = new TrackingSlip("slip");
                String s = ts.getSlip();
            }
    //        TrackingSlip ts = new TrackingSlip("slip"); // 不能用在这里,超出作用域
        }
    
        public void track(){interalTracking(true);}
    
        public static void main(String[] args) {
            Parcel6 p = new Parcel6();
            p.track();
        }
    }
    

    10.6 匿名内部类

    1. 实现了接口的匿名类

    package chapter10Innerclasses;
    
    public class Parcel7 {
        public Contents contents(){
            return new Contents() { // 使用默认构造器生成Contents
                private int i = 11;
    
                @Override
                public int value() {
                    return i;
                }
            }; //需要分号
        }
    
        public static void main(String[] args) {
            Parcel7 p = new Parcel7();
            Contents c = p.contents();
            
        }
    }
    
    
    1. 扩展了有非默认构造器的类

    package chapter10Innerclasses;
    
    class Wrapping {
        private int i ;
        Wrapping(int x) {
            i = x;
            System.out.println("Wrapping constructor x = " + x);
        }
        public int value(){return i;}
    
    }
    
    public class Parcel8 {
        public Wrapping wrapping(int x) { 
            return new Wrapping(x) { // 传参数给构造器
                public int value() {
                    return super.value() * 47;
                }
            }; // 分号
        }
    
        public static void main(String[] args) {
            Parcel8 p = new Parcel8();
            Wrapping w = p.wrapping(10);
            System.out.println(w.value());
    
        }
    }
    
    
    1. 执行字段初始化

    package chapter10Innerclasses;
    
    public class Parcel9 {
        public Destination destination(final String dest){ // 参数必须final JDK 8编译器会自动加上,可以把class文件反编译出来看看,编译期会自动加上final关键字
    //        dest = "test";
    //
    //        String finalDest = dest; //Local variable a defined in an enclosing scope must be final or effectively final
            return new Destination() { // 匿名类 初始化  是Parcel5的简化版
    
                private String label = dest;
                @Override
                public String readLabel() {
                    System.out.println("dest is  " + dest);
                    return label;
                }
            };
        }
    
        public static void main(String[] args) {
            Parcel9 p = new Parcel9();
            Destination d = p.destination("Tasmania");
            System.out.println(d.readLabel());
        }
    }
    
    1. 通过实例初始化实现构造(匿名类不可能有构造器)

    package chapter10Innerclasses;
    
    abstract class Base{
        public Base(int i){
            System.out.println("Base constructor.i = " + i);
        }
        public abstract void f();
    }
    public class AnonymousConstructor {
        public static Base getBase(int i ){
            return new Base(i){ //  变量i 不一定是final 因为i 是被传递给匿名类的基类的构造器,它不会在匿名类内部被直接使用
                {
                    System.out.println("Inside instance initializer");
                }
    
                @Override
                public void f() {
                    System.out.println("In anonymous f()");
                }
            };
        }
    
        public static void main(String[] args) {
            Base base = getBase(47);
            base.f();
        }
    }
    /*
    Base constructor.i = 47
    Inside instance initializer
    In anonymous f()
     */
    
    
    package chapter10Innerclasses;
    // 实例初始化
    public class Parcel10 {
        public Destination destination(final String dest,final float price){
            return new Destination() { // 实现接口
                private int cost;
                // 为每个object 初始化实例
                {
                    cost = Math.round(price);
                    if (cost > 100)
                        System.out.println("Over budget");
                }
                private String label = dest;
                @Override
                public String readLabel() {
                    return label;
                }
            };
        }
    
        public static void main(String[] args) {
            Parcel10 p = new Parcel10();
            Destination d = p.destination("Tasmania",101.295F);
            d.readLabel();
        }
    }
    
    作业12
    package chapter10Innerclasses.e12;
    
    public class ClassA {
        private int i = 10;
        private void methodA(){
            System.out.println("ClassA private methodA(),and i = " + i);
        }
    
        public void methodC(){
            new Object(){
                void methodB(){
                    i++;
                    methodA(); // 内部类可以访问 外围类的私有字段和私有方法
                    System.out.println("ClassA Inner methodB(),and i = " + i);
                }
            }.methodB(); //匿名内部类 实例的方法
            System.out.println("methodC and i = " + i);
        }
    
        public static void main(String[] args) {
            ClassA classA = new ClassA();
            classA.methodC();
        }
    }
    
    

    10.6.1 再访工厂方法

    package chapter10Innerclasses;
    
    interface Service{
        void method1();
        void method2();
    }
    
    interface ServiceFactory{ // 生成某个接口的对象
        Service getService();
    }
    
    class Implementation1 implements Service {
        private Implementation1(){}  // 构造方法 为private
    
        @Override
        public void method1() {
            System.out.println("Implementation1.method1()");
        }
    
        @Override
        public void method2() {
            System.out.println("Implementation1.method2()");
        }
    
        public static ServiceFactory factory = new ServiceFactory(){ // 工厂对象为 static 字段对象
    
            @Override
            public Service getService() {
                return new Implementation1();
            }
        };
    }
    
    //class Implementation1Factory implements ServiceFactory {
    //
    //    @Override
    //    public Service getService() {
    //        return new Implementation1();  //生成接口的某个实现的对象
    //    }
    //}
    
    class Implementation2 implements Service {
        private Implementation2(){}
    
        @Override
        public void method1() {
            System.out.println("Implementation2.method1()");
        }
    
        @Override
        public void method2() {
            System.out.println("Implementation2.method2()");
        }
    
        public static ServiceFactory factory = new ServiceFactory() {
            @Override
            public Service getService() {
                return new Implementation2();
            }
        };
    
    }
    
    //class Implementation2Factory implements ServiceFactory {
    //
    //    @Override
    //    public Service getService() {
    //        return new Implementation2();
    //    }
    //}
    
    public class Factories {
        public static void serviceConsumer(ServiceFactory fact){
            Service s = fact.getService();
            s.method1();
            s.method2();
        }
        public static void main(String[] args) {
            serviceConsumer(Implementation1.factory);
            serviceConsumer(Implementation2.factory);
    
        }
    }
    /*
    Implementation1.method1()
    Implementation1.method2()
    Implementation2.method1()
    Implementation2.method2()
     */
    
    package chapter10Innerclasses;
    
    interface Game{boolean move();}
    
    interface GameFactory{
        Game getGame();}
    
    class Checkers implements Game { //西洋跳棋
        private int moves = 0;
        private static final int MOVES =3;
    
        @Override
        public boolean move() {
            System.out.println("Checkers move " + moves);
            return ++moves != MOVES;
        }
    
        public static GameFactory checkersFactory = new GameFactory(){
    
            @Override
            public Game getGame() {
                return new Checkers();
            }
        };
    }
    
    //class CheckersFactory implements GameFactory {
    //
    //    @Override
    //    public Game getGame() {
    //        return new Checkers();
    //    }
    //}
    
    class Chess implements Game {
        private int moves = 0;
        private static final int MOVES =4;
    
        @Override
        public boolean move() {
            System.out.println("Chess " + moves);
            return ++moves != MOVES;
        }
    
        public static GameFactory chessFactory = new GameFactory() {
            @Override
            public Game getGame() {
                return new Chess();
            }
        };
    }
    
    //class ChessFactory implements GameFactory {
    //
    //    @Override
    //    public Game getGame() {
    //        return new Chess();
    //    }
    //}
    
    public class Games {
        public static void playGame(GameFactory factory){
            Game s = factory.getGame();
            while (s.move())
                ;
        }
    
        public static void main(String[] args) {
            playGame(Checkers.checkersFactory);
            playGame(Chess.chessFactory);
        }
    }
    /*
    Checkers move 0
    Checkers move 1
    Checkers move 2
    Chess 0
    Chess 1
    Chess 2
    Chess 3
     */
    

    优先使用类,而不是接口

    10.7嵌套类

    • 内部类 对象 隐式 保留一个引用 指向创建它的外围类对象
    • static 嵌套类:不需要其外围类的对象
    • 不能从嵌套类的对象中 访问 非静态的 外围类对象
    • 普通内部类 字段方法 放在类的外部层次 不能有static 数据和字段
    • 嵌套类 可以包含
    package chapter10Innerclasses.e18;
    
    
    public class E18 {
        static class NestedClass{
            void f(){
                System.out.println("NestedClass.f()");
            }
        }
    
        public static void main(String[] args) {
            NestedClass ne = new NestedClass(); // 嵌套类内直接使用类名
            ne.f();
        }
    
    
    }
    
    class other { // 类作用域之外,通过outer class.nested class
        void f(){
            E18.NestedClass  ne =new E18.NestedClass();
        }
    }
    
    
    package chapter10Innerclasses.e19;
    
    public class E19 {
        class Inner1{
            class Inner2{
                void f(){}
            }
            Inner2 makeInner2(){return new Inner2();}
        }
        Inner1 makeInner1(){return new Inner1();}
    
        static class Nested1{
            static class Nested2{
                void f(){}
            }
            void f(){}
        }
    
        public static void main(String[] args) {
            new E19.Nested1().f(); // 调用类,不用() 实例化需要生成对象 
            new E19.Nested1.Nested2().f();
            E19 x1 = new E19();
            E19.Inner1 x2 = x1.makeInner1();
            E19.Inner1.Inner2 x3 = x2.makeInner2();
            x3.f();
        }
    }
    /*
    生成的class文件名称
    E19$Inner1$Inner2.class		E19$Nested1.class
    E19$Inner1.class		E19.class
    E19$Nested1$Nested2.class
     */
    
    

    10.7.1接口内部的类

    创建某些公共代码,被某接口所有不同实现所共用。

    package chapter10Innerclasses;
    
    public interface ClassInInterface {
        void howdy();
        class Test implements ClassInInterface{ // 嵌套类可以作为 接口的一部分,放到接口的类 自动都是public static。
            // 类是static ,只是将嵌套类 置于接口的命名空间内,不违反接口规则。甚至可以在内部类中,实现外围接口
    
            @Override
            public void howdy() {
                System.out.println("howdy!");
    
            }
    
            public static void main(String[] args) {
                new Test().howdy();
            }
        }
    }
    
    
    package chapter10Innerclasses;
    
    public class TestBed {
        public void f(){
            System.out.println("f()");
        }
        public static class Tester{
            public static void main(String[] args) {
                TestBed t = new TestBed();
                t.f();
            }
        }
    }
    //每个类中 都写个main()测试 ,缺点: 带着编译后都额外代码
    //嵌套类 放置测试代码,生成两个类
    // TestBed$Tester.class  执行java  TestBed$Tester.class $ 转义
    //TestBed.class
    // 产品打包前删除 TestBed$Tester.class
    
    
    package chapter10Innerclasses.e20;
    
    interface Outer{
        class Inner{
            public void g(){
                System.out.println("Inner.g()");
            }
        }
    }
    public class E20 implements Outer { //即使接口本身没有什么用,但接口中的类仍旧有用。
    
        public static void main(String[] args) {
            E20 e20 = new E20();
            Outer.Inner in = new Outer.Inner();
            in.g();
        }
    }
    
    package chapter10Innerclasses.e21;
    
    interface I{
        void f();
        class C{ //包含嵌套类的接口
            static void g(I i){ // static方法,调用接口中的方法
                System.out.println("calling I.f");
                i.f();
            }
        }
    }
    public class E21 {
        public static void main(String[] args) {
            I impl = new I(){ // 实现接口
                @Override
                public void f() {
    
                }
            };
            I.C.g(impl); // 将实现的实例传递给这个方法
        }
    }
    
    

    10.7.2从多层嵌套类中访问外部类的成员

    package chapter10Innerclasses;
    // 嵌套类 能访问 外围层的所有成员,包括私有,如下例 g() f()
    
    class MNA{
        private void f(){}
        class A{
            private void g(){}
            public class B{
                void h(){
                    g();
                    f();
                }
            }
        }
    
    }
    public class MultiNestingAccess {
        public static void main(String[] args) {
            MNA mna = new MNA();
            MNA.A mnaa = mna.new A(); // .new语法能产生正确的作用域,不必在调用构造器时限定类名
            MNA.A.B mnaab = mnaa.new B();
    
            mnaab.h();
        }
    
    }
    
    

    10.8为什么需要内部类

    内部类提供 某种进入其外围类的窗口

    • 内部类继承自某个类或实现某个接口
    • 内部类的代码 操作 创建它的外围类的对象。

    每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。

    package chapter10Innerclasses;
    // 两种方法 一个类 实现 多个接口
    
    interface  A{}
    interface  B{}
    class X implements A,B{}
    class Y implements A{
        B makeB(){
            return new B(){}; //匿名内部类
        }
    }
    public class MultiInterfaces {
        static void takesA(A a){}
        static void takesB(B a){}
    
        public static void main(String[] args) {
            X x = new X();
            Y y = new Y();
            takesA(x);
            takesA(y);
            takesB(x);
            takesB(y.makeB());// 通过使用内部类实现接口
        }
    }
    
    
    package chapter10Innerclasses;
    // 拥有具体的类或抽象类,而不是接口。只能 内部类 实现多重继承。
    // 若不需要解决 多重问题,可以用其他方式编码
    class D{}
    abstract class E{}
    class Z extends D{
        E makeE(){return new E(){};} //内部类 实现多重继承
    }
    public class MultiImplementation {
        static void takesD(D d){}
        static void takesE(E e){}
    
        public static void main(String[] args) {
            Z z = new Z();
            takesD(z);
            takesE(z.makeE());
        }
    }
    
    

    内部类的其他特性:
    可以有多个实例,每个实例都有自己的状态信息,与外围类对象信息相互独立
    单个外围类,可以多个内部类以不同方式实现一个接口或继承同一个类

    练习22
    package chapter10Innerclasses.e22;
    //
    
    interface Selector{ // 迭代器模式
        boolean end();
        Object current();
        void next();
    }
    
    public class Sequence {
        private Object[] items;
        private int next = 0;
        public Sequence(int size) {items = new Object[size];}
        public void add(Object x){
            if(next < items.length)
                items[next++] = x;
        }
    
        //正序
        private class SequenceSelector implements Selector {
            private int i = 0;
    
            @Override
            public boolean end() {
                return i == items.length;
            }
    
            @Override
            public Object current() {
                return items[i];
            }
    
            @Override
            public void next() {
                if (i < items.length) i++;
    
            }
    
            public Sequence outer(){  // 对外部类 Sequence 的引用
                return Sequence.this;
            }
        }
    
    
        public Selector selector(){
            return new SequenceSelector();
        }
    
        public boolean check(){
            return this == ((SequenceSelector)selector()).outer(); //校验  SequenceSelector 为私有
        }
    
        // 逆序
        private class ReverseSelector implements Selector{
            private int i = items.length -1;
    
            @Override
            public boolean end() {
                return i == 0;
            }
    
            @Override
            public Object current() {
                return items[i];
            }
    
            @Override
            public void next() {
                if(i>0) i--;
    
            }
    
            public Sequence outer(){  // 对外部类 Sequence 的引用
                return Sequence.this;
            }
        }
        public Selector reverseSelector(){return new ReverseSelector();}
    
        public boolean checkReverse(){
            return this == ((ReverseSelector)reverseSelector()).outer(); //校验
        }
    
    
    
        public static void main(String[] args) {
            Sequence sequence = new Sequence(10);
            for (int i = 0;i < 10;i++)
                sequence.add(Integer.toString(i));
            Selector selector = sequence.selector();
            while (!selector.end()){
                System.out.println(selector.current() + " ");
                selector.next();
             }
            System.out.println(sequence.check());
    
            //逆序
            Selector rs = sequence.reverseSelector();
            while (!rs.end()){
                System.out.println(rs.current() + "");
                rs.next();
            }
            System.out.println(sequence.checkReverse());
        }
    }
    
    
    package chapter10Innerclasses.e23;
    
    interface U {
        void method1();
    
        void method2();
    
        void method3();
    }
    
    class A {
        int i = 0;
    
        A(int i) {
            this.i = i;
        }
    
        public U getU() { // 创建一个匿名内部类,生成指向U的引用
            return new U() {
                @Override
                public void method1() {
                    System.out.println("A method1 ,i = " + i);
                }
    
                @Override
                public void method2() {
                    System.out.println("A method2 ,i = " + i);
                }
    
                @Override
                public void method3() {
                    System.out.println("A method3 ,i = " + i);
    
                }
            };
        }
    }
    
    class B {
        private U[] ua; // U的数组,此例子中用A产生的对象来填充
    
        public B(int size) {
            ua = new U[size];
        }
    
        public boolean add(U u, int index) {
            for (int i = 0; i < ua.length; i++) {
                if (ua[i] == null){
                    ua[index] = u;
                    return true;
                }
            }
            return false; // 找不到空位
        }
    
        public boolean setNull(int i) {
            if (i<0 || i>= ua.length)
                return false; // 越界 抛出异常
            ua[i] = null;
            return true;
        }
    
        void callMethods() {
            for (int i = 0; i < ua.length; i++) {
                if (ua[i] != null) {
                    ua[i].method1();
    //                ua[i].method2();
    //                ua[i].method3();
                }
            }
        }
    }
    
    public class E23 {
        public static void main(String[] args) {
            int size = 3;
            B b = new B(size);
            for (int i = 0; i < size; i++) {
                A a = new A(i);
                b.add(a.getU(), i);
            }
            b.callMethods();
            b.setNull(0);
            b.callMethods();
    
    
        }
    }
    /*
    A method1 ,i = 0
    A method1 ,i = 1
    A method1 ,i = 2
    A method1 ,i = 1
    A method1 ,i = 2
     */
    
    

    10.8.1闭包与回调

    闭包的定义:
    • 可调用的对象。记录了来自创建于它的作用域的信息。
    内部类:面向对象的闭包
    • 包含外围类对象的信息
    • 自动拥有外围类对象的引用
    • 内部类可以操作包括private成员
    package chapter10Innerclasses;
    /*闭包 回调
    闭包 用一个类把另一个类包装起来。其构造比内部类复杂。作用有二
    1闭包 能保护内部类里面的变量安全,不会被外部访问
    2 能维持一个变量一直存活在内存中,不被CG掉
    回调
    
    同步调用
    异步调用
    
    回调 与异步 区别,以后补
    */
    
    
    //创建个接口,包含一个函数
    interface Incrementable{
        void increment();
    }
    
    // 接口中没有上面特别的地方,实现这个接口,直接覆盖方法。
    class Callee1 implements Incrementable{
        private int i;
    
        @Override
        public void increment() {
            i++;
            System.out.println(i);
        }
    }
    
    // 和上面接口一样的方法,只是具体实现的方式不一样
    class MyIncrement{
        public void increment(){
            System.out.println("other operation");
        }
    //    static void f(MyIncrement mi){mi.increment();} //测试一下increment方法而已
    }
    
    //如果必须继承上面的MyIncrement的话,那上面已经有了具体的方法实现。把它覆盖,则上面的功能就不能用了
    class Callee2 extends MyIncrement{
        private int i = 0;
    
        public void increment(){// 同样写类这个方法,覆盖父类方法,中间还调用父类方法
            super.increment();
            i++;
            System.out.println(i);
        }
    
        //闭包具体实现 内部类实现类接口,并直接调用外部类的方法作为具体实现。
        private class Closure implements Incrementable{
    
            @Override
            public void increment() {
                // 具体 外围的方法,否则 会 无限回调
                Callee2.this.increment(); //调用外部类的方法
            }
        }
        //钩子getCallbackReference方法, 返回内部类的对象,实现内部和外部的链接。
        //只有Callee2的对象可以访问
        Incrementable getCallbackReference(){return new Closure();}
    
    }
    
    // 专门调用函数的 调用者
    // 唤醒作用,通过接受不同的接口对象,实现不同的操作。
    // 等待接受一个内部类对象,来产生回调。
    class Caller{
        private Incrementable callbackReference;
        Caller(Incrementable cbh){callbackReference = cbh;}
        void go(){callbackReference.increment();}
    }
    
    public class Callbacks {
        public static void main(String[] args) {
            Callee1 c1 = new Callee1();
            Callee2 c2 = new Callee2();
    //        MyIncrement.f(c2);
            System.out.println("------");
            Caller caller1 = new Caller(c1);
            Caller caller2 = new Caller(c2.getCallbackReference()); //
            caller1.go();
            caller1.go();
            System.out.println("------");
            caller2.go();
            caller2.go();
    
        }
    }
    /*
    other operation
    1
    ------
    1
    2
    ------
    other operation
    2
    other operation
    3
     */
    
    

    10.8.2内部类与控制框架

    package chapter10Innerclasses.controller;
    
    // 要控制的事件
    // 基于时间去执行控制,使用抽象类代替实际接口
    public  abstract class Event {
        private long eventTime;
        protected final long delayTime;
    
        public Event(long delayTime) {
            this.delayTime = delayTime;
            start();
        }
        public void start(){ // 没有包含在构造器内,可以允许重启
            eventTime = System.nanoTime() + delayTime;
        }
        public boolean ready(){ //何时可以运行action方法了 在导出类中 可以覆盖ready()方法,使得Event能够基于时间以外的其他因素而触发
            return System.nanoTime() >= eventTime; //当前时间 大于 延时时间,说明已经准备完毕
        }
        public abstract void action(); // 重复事件,则在action中调用start方法
    
    }
    
    package chapter10Innerclasses.controller;
    // 控制系统的可重用的框架
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Controller {
        private List<Event> eventlist = new ArrayList<Event>();
    
        public void addEvent(Event c) {
            eventlist.add(c);
        }
    
        public void run() {
            while (eventlist.size() > 0)
                //对eventList做一个拷贝,免得改动了原来的数据
                for(Event e: new ArrayList<Event>(eventlist))
                    if (e.ready()){
                        System.out.println(e);
                        e.action();
                        eventlist.remove(e);
                    }
        }
    }
    
    
    package chapter10Innerclasses.controller;
    //{Args:5000}
    /*
    功能:控制框架的实现,
    1、控制框架的完整实现是由单个的类创建的,从而使得实现的细节被封装了起来。内部类用来表示解决问题所必须的各种不同的action
    2、内部类能够很容易地访问外围类的任意成员,所以可以避免这种实现变得笨拙。
     */
    public class GreenhouseControl extends Controller {
        private boolean light = false;
    
        public class LightOn extends Event {// //由于event是抽象类,所以必须实现构造函数和抽象函数
    
            public LightOn(long delayTime) {
                super(delayTime);
            }
    
            @Override
            public void action() {
                //
                light = true;
            }
    
            public String toString() {
                return "Light is on";
            }
        }
    
        public class LightOff extends Event {
            public LightOff(long delayTime) {
                super(delayTime);
            }
    
            @Override
            public void action() {
                //
                light = false;
            }
    
            public String toString() {
                return "Light is off";
            }
        }
    
        private boolean water = false;
    
        public class WaterOn extends Event        //由于event是抽象类,所以必须实现构造函数和抽象函数
        {
    
            public WaterOn(long delayTime) {
                super(delayTime);
            }
    
            @Override
            public void action() {
                water = true;
    
            }
    
            public String toString() {
                return "Greenhouse is on";
            }
    
        }
    
        public class WaterOff extends Event        //由于event是抽象类,所以必须实现构造函数和抽象函数
        {
    
            public WaterOff(long delayTime) {
                super(delayTime);
            }
    
            @Override
            public void action() {
                water = false;
    
            }
    
            public String toString() {
                return "Greenhouse is off";
            }
    
        }
    
        private String thermostat = "Day";
    
        public class ThermostatDay extends Event        //由于event是抽象类,所以必须实现构造函数和抽象函数
        {
    
            public ThermostatDay(long delayTime) {
                super(delayTime);
            }
    
            @Override
            public void action() {
                thermostat = "Day";
    
            }
    
            public String toString() {
                return "Thermostat on day setting";
            }
    
        }
    
        public class ThermostatNight extends Event        //由于event是抽象类,所以必须实现构造函数和抽象函数
        {
    
            public ThermostatNight(long delayTime) {
                super(delayTime);
            }
    
            @Override
            public void action() {
                thermostat = "Night";
    
            }
    
            public String toString() {
                return "Thermostat on night setting";
            }
    
        }
    
        public class Bell extends Event {
    
            public Bell(long delayTime) {
                super(delayTime);
            }
    
            @Override
            public void action() {
                addEvent(new Bell(delayTime));
    
            }
    
            public String toString() {
                return "Bing!";
            }
        }
    
        public class Restart extends Event {
            private Event[] eventList;
    
            public Restart(long delayTime, Event[] eventList) {
                super(delayTime);
                this.eventList = eventList;
                for (Event e : eventList)
                    addEvent(e);
            }
    
            @Override
            public void action() {
                for (Event e : eventList) {
                    e.start(); // rerun 每个event
                }
                start(); // rerun 这个事件
                addEvent(this);
    
            }
    
    
            public String toString() {
                return "Restarting system!";
            }
    
        }
    
        public static class Terminate extends Event {
    
            public Terminate(long delayTime) {
                super(delayTime);
            }
    
            @Override
            public void action() {
                System.exit(0);
            }
            public String toString() {
                return "Terminate system!";
            }
        }
    
    
        //配置 并 执行系统
        public static void main(String[] args) {
            GreenhouseControl gc = new GreenhouseControl();
            gc.addEvent(gc.new Bell(900));
            Event[] eventList ={
                    gc.new ThermostatNight(0),
                    gc.new LightOn(200),
                    gc.new LightOff(200),
                    gc.new WaterOn(600),
                    gc.new WaterOff(800),
                    gc.new ThermostatDay(1400),
            };
            gc.addEvent(gc.new Restart(2000,eventList));
            if(args.length == 1)
                gc.addEvent(new GreenhouseControl.Terminate(new Integer(args[0])));
            gc.run();
    
        }
    
    
    }
    
    

    内部类的继承

    package chapter10Innerclasses;
    //内部类的继承
    class WithInner{
        class Inner{}
    }
    public class InheritInner extends WithInner.Inner{
        InheritInner(WithInner wi){
            wi.super(); //这个看不懂
        }
    
        public static void main(String[] args) {
            WithInner wi = new WithInner();
            InheritInner ii = new  InheritInner(wi);
        }
    }
    
    此练习已吐血
    package chapter10Innerclasses.e26;
    
    class WithInner {
        class Inner {
            Inner(int i) {
                System.out.println("Inner i:" + i);
            }
        }
    }
    
    class WithInner2 {
        class Inner2 extends WithInner.Inner {
    
            public Inner2(WithInner wnd, int i) {
                wnd.super(i);
            }
    
        }
    
        public static void main(String[] args) {
            WithInner wi = new WithInner();
            WithInner2 wi2 = new WithInner2();
            Inner2 i2 = wi2.new Inner2(wi, 47);
    
    
        }
    }
    
    public class E26 {
    
    }
    
    

    10.10内部类可以被覆盖吗

    package chapter10Innerclasses;
    // 内部类不能像方法那样被覆盖
    // 继承某个外围类时,相同的内部类,是两个完全独立的实体,各自在自己的命名空间内。
    class Egg{
        private Yolk y;
        protected class Yolk{
            public Yolk(){
                System.out.println("Egg.Yolk()");
            }
        }
        public Egg(){
            System.out.println("New Egg()");
            y = new Yolk();
        }
    }
    public class BigEgg extends Egg{
        public class Yolk{
            public Yolk(){
                System.out.println("BigEgg.Yolk()");
            }
        }
    
        public static void main(String[] args) {
            new BigEgg();
        }
    }
    /* 
    New Egg()
    Egg.Yolk()
     */
    
    
    
    package chapter10Innerclasses;
    // 内部类不能想方法那样被覆盖
    // 但 内部类如果明确继承某个内部类,也是可以的。
    class Egg2{
    
        protected class Yolk{
            public Yolk(){
                System.out.println("Egg2.Yolk()");
            }
            public void f(){
                System.out.println("Egg2.Yolk().f()");
            }
        }
        private Yolk y = new Yolk();
        public Egg2(){
            System.out.println("New Egg2()");
        }
        public void insertYolk(Yolk yy) {y = yy;}
        public void g(){y.f();}
    }
    public class BigEgg2 extends Egg2{
        public class Yolk extends Egg2.Yolk{
            public Yolk(){
                System.out.println("BigEgg2.Yolk()");
            }
            public void f(){
                System.out.println("BigEgg2.Yolk.f()");
            }
        }
        public BigEgg2(){insertYolk(new Yolk());} // 向上转型
    
        public static void main(String[] args) {
            Egg2 egg2 = new BigEgg2();
            egg2.g(); // 调用新的f()
        }
    }
    /*
    Egg2.Yolk()
    New Egg2()
    Egg2.Yolk()
    BigEgg2.Yolk()
    BigEgg2.Yolk.f()
     */
    
    

    局部内部类

    局部内部类:在方法和及方法的作用域内的类
    不能有访问说明符,因为它不是外围类的一部分。
    但可以访问当前代码块的常量,以及外围类的所有成员。

    package chapter10Innerclasses;
    
    interface Counter {
        int next();
    }
    
    public class LocalInnerClass {
        private int count = 0;
    
        // 局部内部类
        Counter getCounter(final String name) {
    
            class LocalCounter implements Counter {
                LocalCounter() {
                    System.out.println("LocalCounter() 构造器");
                }
    
                @Override
                public int next() {
                    System.out.print(name); // 访问local final
                    return count++;
                }
            }
            return new LocalCounter();
        }
    
        // 匿名内部类
        Counter getCounter2(final String name) {
            return new Counter() { // 匿名内部类 没有带名字的构造器,只有一个实例的初始化
                {
                    System.out.println("Counter");
                }
    
                @Override
                public int next() {
                    System.out.print(name); // 访问local final
                    return count++;
                }
            };
        }
    
        public static void main(String[] args) {
            LocalInnerClass lic = new LocalInnerClass();
            Counter c1 = lic.getCounter("局部内部类"),
                    c2 = lic.getCounter2("匿名内部类");
            for (int i = 0; i < 5; i++)
                System.out.println(c1.next());
            for (int i = 0; i < 5; i++)
                System.out.println(c2.next());
        }
    }
    /*
    LocalCounter() 构造器
    Counter
    局部内部类0
    局部内部类1
    局部内部类2
    局部内部类3
    局部内部类4
    匿名内部类5
    匿名内部类6
    匿名内部类7
    匿名内部类8
    匿名内部类9
     */
    

    局部内部类和匿名内部类实现的功能,具有相同的行为和能力。

    • 匿名内部类:用于实例初始化
    • 局部内部类:
      • 理由1:需要一个已经命名的构造器,或者需要重载构造器。
      • 理由2:需要不止一个该内部类的对象。

    10.12内部类标识符

    每个类都生成.class文件

    • Out.class
    • Out$1.class 匿名类
    • Out$1Inner2.class局部内部类
    • Out$Inner3.class内部类嵌套

    10.13总结

  • 相关阅读:
    quick cocos2dx 播放序列帧动画的实现
    PS学习笔记
    python自学笔记(十一)关于函数及书写格式
    python自学笔记(十)语句与数据结构应用
    python自学笔记(九)python练习题
    python自学笔记(八)python语句
    python自学笔记(七)排序与多级排序
    python自学笔记(六)二进制与位移
    python自学笔记(五)python文本操作
    python自学笔记(四)python基本数据类型之元组、集合、字典
  • 原文地址:https://www.cnblogs.com/erinchen/p/11830479.html
Copyright © 2011-2022 走看看