1. 程式人生 > >Thinking in Java 第四版完整版 第七章練習題 複用類

Thinking in Java 第四版完整版 第七章練習題 複用類

Thinking in Java 第四版完整版 第七章練習題,記錄一下(jdk1.8.0)

1.

/**
 * 練習1:建立一個簡單的類。在第二個類中,將一個引用定義為第一個類
 * 的物件。運用惰性初始化來例項化這個物件。
 * @author admin11
 * @date 2018年3月21日
 */

class Simple {
    String s;
    public Simple(String si) {
        s = si;
    }

    public String toString() {
        return s;
    }

    public
void setString(String sNew) { s = sNew; } } class Second { Simple simple; String s; public Second(String si) { s = si; } public void check() { if(simple == null) { System.out.println("not initialized"); } else { System.out.println("initialized"
); } } private Simple lazy() { if(simple == null) { System.out.println("Creating Simple"); simple = new Simple(s); } return simple; } public Simple getSimple() { return lazy(); } public String toString() { return
lazy().toString(); } public void setSimple(String sNew) { lazy().setString(sNew); } } public class Exercise701 { public static void main(String[] args) { Second second = new Second("Init String"); second.check(); System.out.println(second.getSimple()); second.check(); System.out.println(second); second.setSimple("New String"); System.out.println(second); } }

這裡寫圖片描述

2.

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) {
        Cleanser x = new Cleanser();
        x.dilute();
        x.apply();
        x.scrub();
        System.out.println(x);
    }
}

public class Detergent extends Cleanser{

    @Override
    public void scrub() {
        append("Detergent.scrub()");
        super.scrub();
    }

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

    public static void main(String[] args) {
        Detergent x = new Detergent();
        x.dilute();
        x.apply();
        x.scrub();
        x.foam();
        System.out.println(x);
        Cleanser.main(args);
    }
}

這裡寫圖片描述

/**
 * 練習2:從Detergent中繼承產生一個新的類。覆蓋scrub()
 * 並新增一個名為sterilize()的新方法。
 * @author admin11
 * @date 2018年3月21日
 */
public class Exercise702 extends Detergent{

    @Override
    public void scrub() {
        append("Exercise702.scrub()");
    }

    public void sterilize() {
        append("Exercise702.sterilize()");
    }

    public static void main(String[] args) {
        Exercise702 e = new Exercise702();
        e.dilute();
        e.apply();
        e.scrub();
        e.sterilize();
        System.out.println(e);
    }
}

這裡寫圖片描述

3.

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

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

public class Cartoon extends Drawing {

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

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

這裡寫圖片描述

/**
 * 練習3:證明前面這句話。
 * @author admin11
 * @date 2018年3月22日
 */
public class Exercise703 extends Drawing{

    /*即使你不為Cartoon()建立構造器,編譯器也會為你合成一個
     * 預設的構造器,該構造器將呼叫基類的構造器。*/
    public static void main(String[] args) {
        Exercise703 e = new Exercise703();
    }
}

這裡寫圖片描述

4.

/**
 * 練習4:證明基類構造器:(a)總是會被呼叫;
 * (b)在匯出類構造器之前被呼叫。
 * @author admin11
 * @date 2018年3月22日
 */

class Base1 {
    public Base1() {
        System.out.println("Base1");
    }
}

class Derived1 extends Base1 {
    public Derived1() {
        System.out.println("Derived1");
    }
}

class Derived2 extends Derived1 {
    public Derived2() {
        System.out.println("Derived2");
    }
}

public class Exercise704 {

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

這裡寫圖片描述

5.

/**
 * 練習5:建立兩個帶有預設構造器(空引數列表)的類A和類B。
 * 從A中繼承產生一個名為C的新類,並在C內建立一個B類的成員。
 * 不要給C編寫構造器。建立一個C類的物件並觀察其結果。
 * @author admin11
 * @date 2018年3月22日
 */

class A {
    public A() {
        System.out.println("A()");
    }
}

class B {
    public B() {
        System.out.println("B()");
    }
}

class C extends A {
    B b = new B();
}

public class Exercise705 {

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

這裡寫圖片描述

6.

/**
 * 練習6:用Chess.java來證明前一段話。
 * @author admin11
 * @date 2018年3月26日
 */
// 如果不在BoardGame()中呼叫基類構造器,編譯器將“抱怨”無法找到
// 符合Game()形式的構造器。而且,呼叫基類構造器必須是你在匯出類構
// 造器中要做的第一件事(如果你做錯了,編譯器會提醒你的)。
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 x = new Chess();
    }
}

這裡寫圖片描述
這裡寫圖片描述

7.

/**
 * 練習7:修改練習5,使A和B以帶引數的構造器取代預設的構造器。
 * 為C寫一個構造器,並在其中執行所有的初始化。
 * @author admin11
 * @date 2018年3月26日
 */
class A {
    public A(String str) {
        System.out.println("A() " + str);
    }
}

class B {
    public B(String str) {
        System.out.println("B() " + str);
    }
}

class C extends A {
    B b;
    public C(String str) {
        super(str);
        b = new B(str);
    }
}

public class Exercise707 {

    public static void main(String[] args) {
        new C("string");
    }
}

這裡寫圖片描述

8.

/**
 * 練習8:建立一個基類,它僅有一個非預設構造器;再建立一個匯出類,
 * 它帶有預設構造器和非預設構造器。在匯出類的構造器中呼叫基類的構造器。
 * @author admin11
 * @date 2018年3月27日
 */

class Base {
    public Base(int i){
        System.out.println("Base " + i);
    }
}

public class Exercise708 extends Base {

    public Exercise708() {
        super(12);
    }

    public Exercise708(int i) {
        super(i);
    }

    public static void main(String[] args) {
        new Exercise708();
        new Exercise708(20);
    }
}

這裡寫圖片描述

9.

/**
 * 練習9:建立一個Root類,令其含有名為Component1、Component2
 * Component3的類的各一個例項(這些也由你寫)。從Root中派生一個類
 * Stem,也含有上述各“組成部分”。所有的類都應帶有可打印出類的相關資訊
 * 的預設構造器。
 * @author admin11
 * @date 2018年3月27日
 */

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

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

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

class Root {
    Component1 c1 = new Component1();
    Component2 c2 = new Component2();
    Component3 c3 = new Component3();
    public Root() {
        System.out.println("Root");
    }
}

class Stem extends Root {
    Component1 c1 = new Component1();
    Component2 c2 = new Component2();
    Component3 c3 = new Component3();
    public Stem() {
        System.out.println("Stem");
    }
}

public class Exercise709 {

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

這裡寫圖片描述

10.

/**
 * 練習10:修改練習9,使每個類都僅具有非預設的構造器。
 * @author admin11
 * @date 2018年3月27日
 */

class Component1 {
    Component1(String str) {
        System.out.println("Component1 " + str);
    }
}

class Component2 {
    Component2(String str) {
        System.out.println("Component2 " + str);
    }
}

class Component3 {
    Component3(String str) {
        System.out.println("Component3 " + str);
    }
}

class Root {
    Component1 c1 = new Component1("Root");
    Component2 c2 = new Component2("Root");
    Component3 c3 = new Component3("Root");
    public Root(String str) {
        System.out.println("Root " + str);
    }
}

class Stem extends Root {
    Component1 c1 = new Component1("Stem");
    Component2 c2 = new Component2("Stem");
    Component3 c3 = new Component3("Stem");
    public Stem(String str) {
        super(str);
        System.out.println("Stem " + str);
    }
}

public class Exercise710 {

    public static void main(String[] args) {
        new Stem("hi");
    }
}

這裡寫圖片描述

11.

/**
 * 練習11:修改Detergent.java,讓它使用代理。
 * @author admin11
 * @date 2018年3月27日
 */

class Cleanser {
    public Cleanser() {
        System.out.print("Cleanser");
    }

    public void append(String str) {
        System.out.print(" " + str);
    }
    public void dilute() {
        System.out.print(" dilute()");
    }
    public void apply() {
        System.out.print(" apply()");
    }
    public String toString() {
        return "";
    }
    public void scrub() {
        System.out.print(" scrub()");
    }
    public static void main(String[] args) {
        Cleanser c = new Cleanser();
        c.dilute();
        c.apply();
        c.scrub();
    }
}

class DetergentDelegation {
    private Cleanser cleanser = new Cleanser();
    public void append(String a) {
        cleanser.append(a);
    }
    public void dilute() {
        cleanser.dilute();
    }
    public void apply() {
        cleanser.apply();
    }
    public String toString() {
        return cleanser.toString();
    }
    public void scrub() {
        append(" DetergentDelegation.scrub()");
        cleanser.scrub();
    }
    public void foam() {
        append(" foam()");
    }

    public static void main(String[] args) {
        DetergentDelegation x = new DetergentDelegation();
        x.dilute();
        x.apply();
        x.scrub();
        x.foam();
        System.out.println(x);
        System.out.println("Testing base class:");
        Cleanser.main(args);
    }
}

public class Exercise711 {

    public static void main(String[] args) {
        DetergentDelegation.main(args);
    }
}

這裡寫圖片描述

12.

/**
 * 練習12:將一個適當的dispose()方法的層次結構新增到練習9的所有
 * 類中。
 * @author admin11
 * @date 2018年3月27日
 */
class Component1 {
    public Component1() {
        System.out.println("Component1");
    }
    public void dispose() {
        System.out.println("Component1 dispose");
    }
}

class Component2 {
    public Component2() {
        System.out.println("Component2");
    }
    public void dispose() {
        System.out.println("Component2 dispose");
    }
}

class Component3 {
    Component3() {
        System.out.println("Component3");
    }
    public void dispose() {
        System.out.println("Component3 dispose");
    }
}

class Root {
    Component1 c1 = new Component1();
    Component2 c2 = new Component2();
    Component3 c3 = new Component3();
    public Root() {
        System.out.println("Root");
    }
    public void dispose() {
        System.out.println("Root dispose");
        c3.dispose();
        c2.dispose();
        c1.dispose();
    }
}

class Stem extends Root {
    Component1 c1 = new Component1();
    Component2 c2 = new Component2();
    Component3 c3 = new Component3();
    public Stem() {
        super();
        System.out.println("Stem");
    }
    public void dispose() {
        System.out.println("Stem dispose");
        c3.dispose();
        c2.dispose();
        c1.dispose();
        super.dispose();
    }
}

public class Exercise712 {

    public static void main(String[] args) {
        new Stem().dispose();
    }
}

這裡寫圖片描述

13.

/**
 * 練習13:建立一個類,它應帶有一個被過載了三次的方法。繼承產生一個新類,
 * 並新增一個該方法的新的過載定義,展示這四個方法在匯出類中都是可以使用的。
 * @author admin11
 * @date 2018年3月27日
 */
class Animal {
    public void eat() {
        System.out.println("eat...");
    }
    public void eat(int i) {
        System.out.println("eat meat...");
    }
    public void eat(String str) {
        System.out.println("eat leaf...");
    }
}

public class Exercise713 extends Animal {
    public void eat(double d) {
        System.out.println("eat double...");
    }

    public static void main(String[] args) {
        Exercise713 e = new Exercise713();
        e.eat();
        e.eat("hi");
        e.eat(100);
        e.eat(2.3);
    }
}

這裡寫圖片描述

14.

/**
 * 練習14:在Car.java中給Engine新增一個service()方法,
 * 並在main()中呼叫該方法。
 * @author admin11
 * @date 2018年3月27日
 */
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) {}
}

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();
    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();
    }
}

這裡寫圖片描述

15.

public class Exercise715_pro {

    protected void f() {
        System.out.println("f()");
    }
}
import com.test.c07.e15.Exercise715_pro;

/**
 * 練習15:在包中編寫一個類,類應具備一個protected方法。在包外部,
 * 試著呼叫該protected方法並解釋其結果。然後,從你的類中繼承產生
 * 一個類,並從該匯出類的方法內部呼叫該protected方法。
 * @author admin11
 * @date 2018年3月27日
 */
class Derived extends Exercise715_pro {
    public void g() {
        f();
    }
}

public class Exercise715_test {

    public static void main(String[] args) {
        // The method f() from the type Exercise715_pro is not visible
        // new Exercise715_pro().f(); 
        new Derived().g();
    }
}

這裡寫圖片描述

16.

/**
 * 練習16:建立一個名為Amphibian的類。由此繼承產生一個稱為Frog的
 * 類。在基類中設定適當的方法。在main()中,建立一個Frog並向上轉型
 * 至Amphibian,然後說明所有方法都可工作。
 * @author admin11
 * @date 2018年3月27日
 */
class Amphibian {
    public void moveInWater() {
        System.out.println("Moving in Water");
    }
    public void moveOnLand() {
        System.out.println("Moving on Land");
    }
}

class Frog extends Amphibian {}

public class Exercise716 {

    public static void main(String[] args) {
        Amphibian a = new Frog();
        a.moveInWater();
        a.moveOnLand();
    }
}

這裡寫圖片描述

17.

/**
 * 練習17:修改練習16,使Frog覆蓋基類中方法的定義(令新定義使用相同
 * 的方法特徵簽名)。請留心main()中都發生了什麼。
 * @author admin11
 * @date 2018年3月27日
 */
class Frog2 extends Amphibian {
    @Override
    public void moveInWater() {
        System.out.println("frog in Water");
    }
    @Override
    public void moveOnLand() {
        System.out.println("frog on Land");
    }
}

public class Exercise717 {

    public static void main(String[] args) {
        Amphibian a = new Frog2();
        a.moveInWater();
        a.moveOnLand();
    }
}

這裡寫圖片描述

18.

/**
 * 練習18:建立一個含有static final域和final域的類,說明二者間的區別。
 * @author admin11
 * @date 2018年3月27日
 */
class SelfCounter {
    private static int count;
    private int id = count++;
    public String toString() {
        return "SelfCounter " + id;
    }
}

class WithFinalFields {
    final SelfCounter scf = new SelfCounter();
    static final SelfCounter scsf = new SelfCounter();
    public String toString() {
        return "scf = " + scf + "\nscsf = " + scsf;
    }
}

public class Exercise718 {
    // 因為類裝載初始化了static final型別的變數,所以在兩次
    // 建立WithFinalFields例項時都具有相同的值。而常規的final
    // 的值在每一個例項中都是不同的。
    public static void main(String[] args) {
        System.out.println("First object:");
        System.out.println(new WithFinalFields());
        System.out.println("Second object:");
        System.out.println(new WithFinalFields());
    }
}

這裡寫圖片描述

19.

/**
 * 練習19:建立一個含有指向某物件的空白final引用的類。在所有構造器
 * 內部都執行空白final的初始化動作。說明Java確保final在使用前
 * 必須被初始化,且一旦被初始化即無法改變。
 * @author admin11
 * @date 2018年3月27日
 */
class WithBlankFinalField {
    private final Integer i;
    // The blank final field i may not have been initialized
    public WithBlankFinalField(int cnt) {
        i = new Integer(cnt);
    }

    public Integer geti() {
        // The final field WithBlankFinalField.i cannot be assigned
//      if(i == null)
//          i = new Integer(47);
        return i;
    }
}

public class Exercise719 {

    public static void main(String[] args) {
        WithBlankFinalField w = new WithBlankFinalField(10);
        System.out.println(w.geti());
    }
}

這裡寫圖片描述

20.

/**
 * 練習20:展示@Override註解可以解決本節中的問題。
 * @author admin11
 * @date 2018年3月27日
 */
class WithFinals {
    private final void f() {
        System.out.println("WithFinals.f()");
    }
    public void g() {
        System.out.println("WithFinals.g()");
    }
}

class OverridingPrivate extends WithFinals{
    private final void f() {
        System.out.println("OverridingPrivate.f()");
    }
    public 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("OverridingPrivate2.g()");
    }
}

public class Exercise720 {

    public static void main(String[] args) {
        OverridingPrivate2 op2 = new OverridingPrivate2();
        op2.f();
        op2.g();
    }
}

這裡寫圖片描述

21.

/**
 * 練習21:建立一個帶final方法的類。由此繼承產生一個類並嘗試
 * 覆蓋該方法。
 * @author admin11
 * @date 2018年3月27日
 */
class WithFinalMethod {
    final void f() {}
}

public class Exercise721 extends WithFinalMethod{
    // Cannot override the final method from WithFinalMethod
    // void f() {}
}

22.

/**
 * 練習22:建立一個final類並試著繼承它。
 * @author admin11
 * @date 2018年3月27日
 */
final class FinalClass {}
// The type Exercise722 cannot subclass 
// the final class FinalClass
public class Exercise722 extends FinalClass {
    // final類不能被繼承
}

23.

/**
 * 練習23:請證明載入類的動作僅發生一次。證明該類的第一個實體的建立
 * 或者對static成員的訪問都有可能引起載入。
 * @author admin11
 * @date 2018年3月27日
 */
class LoadTest {
    static {
        System.out.println("Loading LoadTest");
    }
    static void staticMember() {}
}

public class Exercise723 {

    public static void main(String[] args) {
        System.out.println("Calling static member");
        LoadTest.staticMember();
        System.out.println("Creating an object");
        new LoadTest();
    }
}

這裡寫圖片描述

24.

class Insect {
    private int i = 9;
    protected int j;
    Insect() {
        System.out.println("i = " + i + ", 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();
    }
}

這裡寫圖片描述

/**
 * 練習24:在Beetle.java中,從Beetle類繼承產生一個具體型別
 * 的“甲殼蟲”。其形式與現有類相同,跟蹤並解釋其輸出結果。
 * @author admin11
 * @date 2018年3月27日
 */
public class Exercise724 extends Beetle {
    int m = printInit("Exercise724.m initialized");
    public Exercise724() {
        System.out.println("m = " + m);
        System.out.println("j = " + j);
    }
    static int x3 = printInit("static Exercise724.x3 initialized");

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

這裡寫圖片描述