组合 新类中产生 现有类的对象
继承 现有类的形式并其中添加新代码

7.1组合语法

将对象置于新类:直接定义基本类型;非基本类型对象,引用置于新类;

package chapter7reusing;
// Composition for code reuse.

class WaterSource {
    private String s;

    WaterSource() {
        System.out.println("WaterSource()");
        s = "Constructed";
    }

    public String toString() { //每一个非基本类型对象都有 toString方法
        return s;
    }
}

public class SprinklerSystem {
    private String valve1, valve2, valve3, valve4;
    private WaterSource source = new WaterSource();
    private int i;
    private float f;

    public String toString() {
        return
                "valve1 = " + valve1 + " " +
                        "valve2 = " + valve2 + " " +
                        "valve3 = " + valve3 + " " +
                        "valve4 = " + valve4 + " " +
                        "i = " + i + " " +
                        "f = " + f + " " +
                        "source = " + source;//调用toString(),将source对象转换为String
    }

    public static void main(String[] args) {
        SprinklerSystem sprinklerSystem = new SprinklerSystem();
        System.out.println(sprinklerSystem); // 基本类型 初始化为0 对象引用初始化为null
    }
}
/* outpub:
WaterSource()
valve1 = null valve2 = null valve3 = null valve4 = null i = 0 f = 0.0 source = Constructed

四种方式初始化

  1. 定义对象的地方
  2. 类的构造器
  3. 惰性初始化
  4. 使用实例初始化
package chapter7reusing;
//Constructor initialization with composition

import static chapter6access.Print.print;

class Soap {
    private String s;

    Soap() { // 类的构造器中
        print("Soap()");
        s = "Constructed";
    }

    public String toString() {
        return s;
    }

}

public class Bath {
    private String //定义对象的地方初始化,构造器被调用之前初始化
            s1 = "Happy",
            s2 = "Happy",
            s3, s4;
    private Soap castille;
    private int i;
    private float toy;

    public Bath() {
        print("Inside Bath()");
        s3 = "Joy";
        toy = 3.14f;
        castille = new Soap(); // 使用实例初始化
    }

    {
        i = 47;
    }

    public String toString() {
        if (s4 == null) //惰性初始化:使用对象之前初始化
            s4 = "Joy";
        return
                "s1 = " + s1 + "\n" +
                        "s2 = " + s2 + "\n" +
                        "s3 = " + s3 + "\n" +
                        "s4 = " + s4 + "\n" +
                        "i = " + i + "\n" +
                        "toy = " + toy + "\n" +
                        "castille = " + castille;
    }

    public static void main(String[] args) {
        Bath bath = new Bath();
        print(bath);
    }

}

惰性初始化 实例第一个类的对象

package chapter7reusing;

class First {
    String s;

    public First(String si) {
        System.out.println("FirstClass()");
        s = si;
    }

    public String toString() {
        return s;
    }

    public void setString(String sNew) {
        s = sNew;
    }

}

class Second {
    String s;
    First first;

    public Second(String si) {
        s = si;
    }

    public void check() {
        if (first == null)
            System.out.println("not initialized");
        else
            System.out.println("initialized");
    }

    private First lazy() {
        if (first == null) {
            System.out.println("create first");
            first = new First(s);
        }
        return first;
    }

    public First getFirst() {
        return lazy();
    }

    public String toString() {
        return lazy().toString();
    }

    public void setFirst(String s) {
        lazy().setString(s);
    }
}

public class E01_Composition {
    public static void main(String[] args) {
        Second second = new Second(("init String"));
        second.check();
        System.out.println(second.getFirst());
        second.check();
        System.out.println(second);
        second.setFirst("New String");
        System.out.println(second);
    }
} /* Output:
not initialized
create first
FirstClass()
init String
initialized
init String
New String
*/

7.2继承语法

隐式继承 标准根类Object

package chapter7reusing;
// Inheritance syntax & properties.

import javax.swing.*;

class Cleanser {
    private String s = "Cleanser";

    public void append(String a) {
        s += a;
    }

    public void dilute() {
        append(" dilute()");
    }

    public void apply() {
        append(" apply()");
    }

    public void scrub() {
        append(" scrub()");
    }

    public String toString() {
        return s;
    }

    public static void main(String[] args) {  //每个类中设置main方法  单元测试简便易行,无需删除
        Cleanser cleanser = new Cleanser();
        cleanser.dilute();
        cleanser.apply();
        cleanser.scrub();
        System.out.println(cleanser);
    }

}

class NewDetergent extends Detergent {
    // 覆盖scrub()
    public void scrub() {
        append("NewDetergent.scrub()");
        super.scrub();
    }
    // 增加方法
    public void sterilize(){ //灭菌
        append(" sterilize()");
    }

    public static void main(String[] args) {
        NewDetergent newDetergent = new NewDetergent();
        newDetergent.dilute();
        newDetergent.apply();
        newDetergent.scrub();
        newDetergent.foam();
        newDetergent.sterilize();
        System.out.println(newDetergent);
    }/* Output:
    Cleanser dilute() apply()NewDetergent.scrub() Detergent.scrub() scrub() foam() sterilize()
    */
}

public class Detergent extends Cleanser {
    // 更改方法
    public void scrub() {
        append(" Detergent.scrub()");
        super.scrub(); //调用基类
    }

    // 增加接口方法
    public void foam() {
        append(" foam()");
    }

    //测试新类
    public static void main(String[] args) {
        Detergent detergent = new Detergent();
        detergent.dilute();
        detergent.apply();
        detergent.scrub();
        detergent.foam();
        System.out.println(detergent);
        System.out.println("Testing base class:");
        Cleanser.main(args);
    }
}/* Output:
Cleanser dilute() apply() Detergent.scrub() scrub() foam()
Testing base class:
Cleanser dilute() apply() scrub()
*/

7.2.1 初始化基类

基类 导出类
创建一个导出类的对象时,该对象也包含一个基类的子对象。
在构造器中调用基类构造器进行初始化。基类构造器具有初始化基类的能力。

package chapter7reusing;


class Art {
    Art() {
        System.out.println("Art constructor");
    }
}

class Drawing extends Art {
    Drawing() {
        System.out.println("Drawing constructor");
    }

}

public class Cartoon extends Drawing {
    Cartoon() { 
        System.out.println("Cartoon constructor");
    }

    public static void main(String[] args) {
        Cartoon x = new Cartoon();
    }
}/* Output: 构建过程 从 基类 向外 扩散
Art constructor
Drawing constructor
Cartoon constructor
*/

package chapter7reusing;

class ClassA {
    ClassA() {
        System.out.println("ClassA()");
    }
}

class ClassB {
    ClassB() {
        System.out.println("ClassB()");
    }
}

class ClassC extends ClassA {
    ClassB classB = new ClassB();
}

public class E05 {
    public static void main(String[] args) {
        ClassC classC = new ClassC();
    }
}/* Output 先调用基类构造方法,然后是成员对象的构造方法
ClassA()
ClassB()
*/

带参数的构造器

必须关键字 super显示调用基类构造器,并适当的参数列表

package chapter7reusing;

class Game {
    Game(int i) {
        System.out.println("Game Constructor");
    }
}

class BoardGame extends Game {
    BoardGame(int i) {
        super(i);
        System.out.println("BoardGame constructor");
    }
}

public class Chess extends BoardGame {
    Chess() {
        super(11);
        System.out.println("Chess Constructor");
    }

    public static void main(String[] args) {
        Chess chess = new Chess();
    }
}/* Output
Game Constructor
BoardGame constructor
Chess Constructor
*/

7.3 代理

public class SpaceShipControl {
    void up(int velocity){};
    void down(int velocity){};
    void left(int velocity){};
    void right(int velocity){};
    void forward(int velocity){};
    void back(int velocity){};
    void turboBoost(){};
}

package chapter7reusing;

public class SpaceShipDelegation {
    private String name;
    private SpaceShipControl control = new SpaceShipControl(); // 成员对象置于类中(就像组合)

    public SpaceShipDelegation(String name) {
        this.name = name;
    }

    //Delegated methods;
    public void back(int velocity) {
        control.back(velocity);
    }

    public void up(int velocity) {
        control.up(velocity);
    }

    public void down(int velocity) {
        control.down(velocity);
    }

    public void forward(int velocity) {
        control.forward(velocity);
    }

    public void left(int velocity) {
        control.left(velocity);
    }

    public void right(int velocity) {
        control.right(velocity);
    }

    public void turboBoost(int velocity) {
        control.turboBoost();
    }

    public static void main(String[] args) {
        SpaceShipDelegation protector = new SpaceShipDelegation("NSEA Protector");
        protector.forward(100);
    }
}

7.4结合使用组合和继承

package chapter7reusing;

class Plate {
    Plate(int i) {
        System.out.println("Plate constructor");
    }
}

class DinnetPlate extends Plate {

    DinnetPlate(int i) {
        super(i);
        System.out.println("DinnetPlate constructor");
    }
}

class Utensil { //器皿
    Utensil(int i) {
        System.out.println("Utensil constructor");
    }
}

class Spoon extends Utensil {

    Spoon(int i) {
        super(i);
        System.out.println("Spoon constructor");
    }
}

class Fork extends Utensil {

    Fork(int i) {
        super(i);
        System.out.println("Fork constructor");
    }
}

class Knife extends Utensil {

    Knife(int i) {
        super(i);
        System.out.println("Knife constructor");
    }
}


class Custom {
    Custom(int i) {
        System.out.println("Custom constructor");
    }
}

public class PlaceSetting extends Custom {
    private Spoon sp;
    private Fork frk;
    private Knife kn;
    private DinnetPlate dp;

    public PlaceSetting(int i) {
        super(i + 1);
        sp = new Spoon(i + 2);
        frk = new Fork(i + 3);
        kn = new Knife(i + 4);
        dp = new DinnetPlate(i + 5);
        System.out.println("PlaceSetting constructor");
    }

    public static void main(String[] args) {
        PlaceSetting x = new PlaceSetting(9);
    }
}

7.4.1 确保正确清理

不建议使用finalize()

package chapter7reusing;
// Ensuring proper cleanup


class Shape {
    Shape(int i) {
        System.out.println("Shape constructor");
    }

    void dispose() {
        System.out.println("Shape dispose");
    }
}

class Circle extends Shape {
    Circle(int i) {
        super(i);
        System.out.println("Drawing Circle");
    }

    void dispose() {
        System.out.println("Erasing Circle");
        super.dispose();
    }
}

class Triangle extends Shape {
    Triangle(int i) {
        super(i);
        System.out.println("Drawing Triangle");
    }

    void dispose() {
        System.out.println("Erasing Triangle");
        super.dispose();
    }
}

class Line extends Shape {
    private int start, end;

    Line(int start, int end) {
        super(start);
        this.start = start;
        this.end = end;
        System.out.println("Drawing Line: " + start + ", " + end);
    }

    void dispose() {
        System.out.println("Erasing Line" + start + ", " + end);
        super.dispose();
    }
}

public class CADSystem extends Shape {
    private Circle c;
    private Triangle t;
    private Line[] lines = new Line[3];

    public CADSystem(int i) {
        super(i + 1);
        for (int j = 0; j < lines.length; j++)
            lines[j] = new Line(j, j * j);
        c = new Circle(1);
        t = new Triangle(1);
        System.out.println("Combined constructor");
    }

    public void dispose() { //注意与初始化的顺序相反 防止子对象依赖另一个子对象
        System.out.println("CADSystem.dispose()");
        t.dispose();
        c.dispose();
        for (int i = lines.length - 1; i >= 0; i--)
            lines[i].dispose();
        super.dispose();
    }

    public static void main(String[] args) {
        CADSystem x = new CADSystem(47);
        try {
            // Code and exception handing……
        } finally {
            x.dispose();
        }
    }
}

7.4.2 名称屏蔽

重载机制 在导出类或基类 都正常工作

package chapter7reusing;

class Homer {
    char doh(char c) {
        System.out.println("doh(char)");
        return 'd';
    }

    float doh(float f) {
        System.out.println("doh(float)");
        return 1.0f;
    }
}

class Milhouse {

}

class Bart extends Homer {
    void doh(Milhouse m) {
        System.out.println("doh(Milhouse)");
    }
}

public class Hide {
    public static void main(String[] args) {
        Bart b = new Bart();
        b.doh(1);
        b.doh('x');
        b.doh(1.0f);
        b.doh(new Milhouse());
    }
}

7.5 组合与继承之间选择

package chapter7reusing;

class Engine {
    public void start() {
    }

    public void rev() {
    }

    public void stop() {
    }
    public void service(){
        System.out.println("service");
    }
}

class Wheel {
    public void inflate(int psi) {
    } //inflate 充气
}

class Window {
    public void rollup() {
    }

    public void rolldown() {
    }
}

class Door {
    public Window window = new Window();

    public void open() {
    }

    public void close() {
    }
}

public class Car {
    public Engine engine = new Engine(); //特例,一般是private 有助于客户端程序员了解如何使用类
    public Wheel[] wheel = new Wheel[4];
    public Door
            left = new Door(),
            right = new Door();

    public Car() {
        for (int i = 0; i < 4; i++)
            wheel[i] = new Wheel();
    }

    public static void main(String[] args) {
        Car car = new Car();
        car.left.window.rollup();
        car.wheel[0].inflate(72);
        car.engine.service();
    }

}

7.6 protected 关键字

protected 对于类用户而言,是private,但对于导出类,或包内的类来说,是可访问的。

package chapter7reusing;

// The protected keyword.
class Villain {
    private String name;

    protected void set(String nm) {
        name = nm;
    }

    public Villain(String name) {
        this.name = name;
    }

    public String toString() {
        return "I'm a Villain and my name is " + name;
    }
}

public class Orc extends Villain {
    private int orcNumber;

    public Orc(String name, int orcNumber) {
        super(name);
        this.orcNumber = orcNumber;
    }

    public void change(String name, int orcNumber) {
        set(name); // Available because it's protected.
        this.orcNumber = orcNumber;
    }

    public String toString() {
        return "Orc" + orcNumber + ": " + super.toString();  // 根据基类版本
    }

    public static void main(String[] args) {
        Orc orc = new Orc("Limburger", 12);
        System.out.println(orc);
        orc.change("Bob", 19);
        System.out.println(orc);
    }

}

向上转型

术语来源: 类继承图 绘制方法为基础
导出类 是 基类的 一个超集,向上转型过程中,唯一可能 是丢失方法

class Instrument {
    public void play() {
        System.out.println("Instrument  play()");
    }

    static void tune(Instrument i) {
        i.play();
    }
}

public class Wind extends Instrument {
    public static void main(String[] args) {
        Wind flute = new Wind();
        Instrument.tune(flute); // 将 Wind引用转换为Instruments 引用的动作: 向上转型
    }
}

再论组合与继承

最可能:
数据和方法包装一个类中,使用该类对象。
组合技术 使用现有类,开发新类。
继承技术不太常用。 必须向上转型,继承必要

package chapter7reusing;

class Amphibian {
    public void swim() {
        System.out.println("swim");
    }

    static void action(Amphibian am) {
        System.out.println("Amphibian: ");
        am.swim();
    }
}

public class Frog extends Amphibian {
 //   public void swim() {
  //      System.out.println("Frog");
    }

    public static void main(String[] args) {
        Frog frog = new Frog();
        Amphibian.action(frog); //使用基类的静态方法
    }
}

或者

package chapter7reusing;

class Amphibian {
public void swim() {
System.out.println("swim");
}

static void action(Amphibian am) {
    System.out.println("Amphibian: ");
    am.swim();
}

}

public class Frog extends Amphibian {
// public void swim() { //覆盖基类的定义,则调用导出类的方法
// System.out.println("Frog");
// }

public static void main(String[] args) {
    Amphibian frog = new Frog(); //定义时 向上转型
    frog.action(frog);
}

}


## 7.8 final关键字
设计  效率
用到final 的几种情况:数据 方法 类
final 在字段定义或者构造器中 初始化

### 7.8.1 final 数据
1.永不改变的编译时常量  大写 下划线分隔单词
2.运行时初始化的值,不希望它被改变

```java
package chapter7reusing;

import javax.swing.*;
import java.util.Random;

class Value {
    int i;

    public Value(int i) {
        this.i = i;
    }
}

public class FinalData {
    private static Random random = new Random(47);
    private String id;

    public FinalData(String id) {
        this.id = id;
    }

    // 编译时数值 final基本类型  编译期常量
    private final int valueOne = 9;
    private static final int VALUE_TWO = 99;
    // 典型 定义  public 可用于包之外 static 只有一份 final 常量
    public static final int VALUE_THREE = 39;

    // 非编译期常量 数据是final,但运行时随机生成数值初始化
    private final int i4 = random.nextInt(20);
    static final int INT_5 = random.nextInt(20);

    private Value v1 = new Value(11);
    private final Value v2 = new Value(22); // v2 不能指向另一个新对象
    private static final Value VAL_3 = new Value(33);
    // Arrays:
    private final int[] a = {1, 2, 3, 4, 5, 6};
    public String toString(){
        return id + ":" + "i4 = " + i4 + ", INT_5 = " +INT_5;
    }

    public static void main(String[] args) {
        FinalData fd1 = new FinalData("fd1");
//        fd1.valueOne++; // final 变量
        fd1.v2.i++; // 对象不是常量
        fd1.v1 = new Value(9); //可以,不是final
        for(int i =0;i<fd1.a.length;i++)
            fd1.a[i]++; // 对象不是常量
//        fd1.v2 = new Value(0); // can't
//        fd1.VAL_3 = new Value(1); // can't
//        fd1.a = new int[3];
        System.out.println(fd1);
        System.out.println("Creating new FinalData");
        FinalData fd2 = new FinalData("fd2");
        System.out.println(fd1);
        System.out.println(fd2);

    }

}

空白final
声明为final 但未给定初值的字段

package chapter7reusing;

class Poppet {
    private int i;

    Poppet(int ii) {
        i = ii;
    }
}

public class BlankFinal {
    private final int i = 0; // 初始化 final
    private final int j; // 空白final
    private final Poppet p; // 空白引用 final

    // 空白final 必须在 构造方法中 初始化
    public BlankFinal() {
        j = 1;
        p = new Poppet(1);
    }

    public BlankFinal(int x) {
        j = x;
        p = new Poppet(x);
    }

    public static void main(String[] args) {
        new BlankFinal();
        new BlankFinal(47);
    }
}


final 参数

无法在方法中更改参数引用所指向的对象

package chapter7reusing;

class Gizmo {
    public void spin() {
    }
}

public class FinalArguments {
    void with(final Gizmo g) {
//        g = new Gizmo(); // g是 final
    }

    void without(Gizmo g) {
        g = new Gizmo();
        g.spin();
    }

    //    void f(final int i) { // 无法修改参数
//        i++;
//    }
    int g(final int i) { // 可以读参数
        return i + 1;
    }

    public static void main(String[] args) {
        FinalArguments bf = new FinalArguments();
        bf.without(null);
        bf.with(null);
    }
}

7.8.2 final 方法

方法锁定,防止 继承类修改 不会被覆盖
效率 不建议

final 和private 关键字
类中private方法 隐式 指定final

方法为private , 就不是基类接口但一部分
覆盖错觉:并没有覆盖,而是生成了一个新的方法

package chapter7reusing;

class WithFinals {
    private final void f() {
        System.out.println("WithFinals.f()");
    }

    private void g() {
        System.out.println("WithFinals.g()"); // 隐式 final
    }
}

class OverridingPrivate extends WithFinals {
    private final void f() {
        System.out.println("OverridingPrivate.f()");
    }

    private void g() {
        System.out.println("OverridingPrivate.g()");
    }
}

class OverridingPrivate2 extends OverridingPrivate {
    public final void f() {
        System.out.println("OverridingPrivate2.f()");
    }

    public void g() {
        System.out.println();
    }
}

public class FinalOverRidingIllusion {
    public static void main(String[] args) {
        OverridingPrivate2 op2 = new OverridingPrivate2();
        op2.f();
        op2.g();
        OverridingPrivate op = op2; // 向上转型 但不能调用方法
//        op.f();
//        op.g();
        WithFinals wf = op2;
//        wf.f();
//        wf.g();
    }
}

7.8.3 final 类

final 类,禁止继承,所有方法隐式指定为final

7.8.4 final 忠告

关于Vector/ArrayList Hashtable/HashMap 关于 Final没看明白

7.9 初始化 及 类的加载

基类static 初始化 - 导出类 static 初始化 类加载完毕
-创建对象
基本类型初始化0 对象引用初始化null
基类构造器 导出类构造器
实例变量

构造器 本质是 静态方法
经典
package chapter7reusing;

class Insect {
    private int i = 9;
    protected int j;

    Insect() {
        System.out.println("i = " + j + ",j +" + j);
        j = 39;
    }

    private static int x1 = printInit("static Insect.x1 initialized");

    static int printInit(String s) {
        System.out.println(s);
        return 47;
    }
}

public class Beetle extends Insect {
    private int k = printInit("Beetle.k initialized");

    public Beetle() {
        System.out.println("k = " + k);
        System.out.println("j = " + j);
    }

    private static int x2 = printInit("static Beetle.x2 initialized");

    public static void main(String[] args) {
        System.out.println("Beetle Constructor");
        Beetle b = new Beetle();
    }
}/* Output
static Insect.x1 initialized
static Beetle.x2 initialized
Beetle Constructor
i = 0,j +0
Beetle.k initialized
k = 47
j = 39
*/
class LoadTest {
    // The static clause is executed
    // upon class loading:
    static {
        System.out.println("Loading LoadTest");
    }
    static void staticMember() {}
}
public class E23_ClassLoading {
    public static void main(String[] args) {
        System.out.println("Calling static member");
        LoadTest.staticMember();
        System.out.println("Creating an object");
        new LoadTest();
    }
} /* Output:
 Calling static member
 Loading LoadTest
 Creating an object
 *///:~
 posted on 2019-10-31 10:33  erinchen  阅读(120)  评论(0编辑  收藏  举报