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

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

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总结

 posted on 2019-11-10 15:40  erinchen  阅读(210)  评论(0编辑  收藏  举报