java编程思想第4版 第七章习题

练习1:

创建一个简单的类。在第二个类中,将一个引用定义为第一个类的对象。运用惰性初始化来实例化这个对象。

代码


public class TestConstructor {

    //惰性初始化对象
    HumanResource humanResource;

    public static void main(String[] args) {
        TestConstructor testConstructor = new TestConstructor();
        testConstructor.print();
    }

    public void print() {
        humanResource = new HumanResource(10);
        //打印对象类型和地址
        System.out.println(humanResource);
    }
}

输出

HumanResource@4554617c

练习2:

从Detergent中继承产生一个新的类。覆盖scrub()并添加一个名为sterilize()的新方法。
代码

package testPackage;

public class Detergent {

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

import testPackage.Detergent;

public class InheritDetergent extends Detergent {

    @Override
    public void scrub() {
        System.out.println("InheritDetergent scrub");
    }

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


    public static void main(String[] args) {
        InheritDetergent inheritDetergent = new InheritDetergent();
        inheritDetergent.scrub();
        inheritDetergent.sterilize();
    }

}

输出

InheritDetergent scrub
sterilize

练习3:

验证构建过程是向外扩散的。

代码

package testPackage;

public class Art {
    public Art() {
        System.out.println("Art");
    }
}
package testPackage;

public class Drawing extends Art {
    public Drawing() {
        System.out.println("create Drawing");
    }
}
package testPackage;

public class Cartoon extends Drawing {
    public static void main(String[] args) {
        Cartoon cartoon = new Cartoon();
    }
}

输出

Art
create Drawing

练习4:

证明基类构造器:a.总是会被调用;b.在导出类构造器之前被调用。

代码

package testPackage;

public class Art {
    public Art() {
        System.out.println("Art");
    }
}
package testPackage;

public class Drawing extends Art {
    public Drawing() {
        System.out.println("create Drawing");
    }
}
package testPackage;

public class Cartoon extends Drawing {

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

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


输出

Art
create Drawing
Cartoon

由此可证。

练习5:

创建两个带有默认构造器(空参数列表)的类A和类B。从A中继承产生一个名为C的新类,并在C内创建一个B类的成员。不要给C编写构造器。创建一个C类的对象并观察其结果。
代码

package access.local;

public class AClass {
    public AClass() {
        System.out.println("create AClass");
    }
}
package access.local;

public class BClass {
    public BClass() {
        System.out.println("create BClass");
    }
}
package access.local;

public class CClass extends AClass {
    BClass bClass = new BClass();

    public static void main(String[] args) {
        CClass cClass = new CClass();
    }
}

输出

create AClass
create BClass

如果在CClass的构造器中添加打印,B的打印会在C之前。
如果采用惰性加载的方式,C打印会在B打印之前。

练习6:

验证:继承类构造器必须调用父类构造器。

如果不调用编译器就会报错

练习7:

修改练习5,使A和B以带参数的构造器取代默认的构造器。为C写一个构造器,并在其中执行所有的初始化。

package access.local;

public class AClass {
    public AClass(int i) {
        System.out.println("create AClass");
    }
}

package access.local;

public class BClass {
    public BClass(int i) {
        System.out.println("create BClass");
    }
}

package access.local;

public class CClass extends AClass {
    BClass bClass;

    public CClass() {
        super(1);
        System.out.println("create CClass");
    }

    public static void main(String[] args) {
        CClass cClass = new CClass();
        cClass.bClass = new BClass(1);
    }
}

输出

create AClass
create CClass
create BClass

练习8:

创建一个类,它仅有一个非默认构造器;再创建一个导出类,他带有默认构造器和非默认构造器。在导出类的构造器中调用基类的构造器。
代码

package access.local;

public class Game {
    public Game(int integral) {
        System.out.println(integral);
    }
}
package access.local;

public class BoardGame extends Game {

    public BoardGame() {
        super(0);
    }

    public BoardGame(int integral) {
        super(integral);
    }
    
    public static void main(String[] args) {
        BoardGame boardGame = new BoardGame();
    }
}

输出

0

练习9:

创建一个Root类,令其含有名为Component1、Commponent、Componen3的类的各一个实例。从Root中派生出一个类Stem,也含有上述各“组成部分”。所有的类都应带有可打印出类的相关信息的默认构造器。
代码

package access.local;

public class Root {

    protected Component1 component1 = new Component1();
    protected Component2 component2 = new Component2();
    protected Component3 component3 = new Component3();

    public Root() {
        System.out.println("RootClass");
    }


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

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

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


    public static class Stem extends Root {
        public Stem() {
            System.out.println("Stem");
        }

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

输出

Component1
Component2
Component3
RootClass
Stem

练习10:

修改练习9,使每个类仅具有非默认的构造器。

代码

package access.local;
package access.local;

public class Root {

    protected Component1 component1 = new Component1(66);
    protected Component2 component2 = new Component2(66);
    protected Component3 component3 = new Component3(66);

    public Root(int i) {
        System.out.println("RootClass" + i);
    }


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

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

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


    public static class Stem extends Root {
        public Stem(int i) {
            super(i);
            System.out.println("Stem" + i);
        }

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


输出

Component166
Component266
Component366
RootClass666
Stem666

练习11

修改Detergent.java,让他使用代理。
代码

package testPackage;

public class Detergent {

    public void scrub(){
        System.out.println("scrub");
    }
}
package testPackage;

public class ProtectedDetergent {

    private final Detergent detergent = new Detergent();

    public void scrub() {
        detergent.scrub();
    }

    public static void main(String[] args) {
        ProtectedDetergent protectedDetergent = new ProtectedDetergent();
        protectedDetergent.scrub();
    }
}


输出

scrub

练习12:

将一个适当的dispose()方法的层次结构添加到练习9的所有类中。
代码

package access.local;

public class Root {

    protected Component1 component1 = new Component1(66);
    protected Component2 component2 = new Component2(66);
    protected Component3 component3 = new Component3(66);

    public Root(int i) {
        System.out.println("RootClass" + i);
    }

    public void dispose() {
        System.out.println("Root dispose");
        component1 = null;
        component2 = null;
        component3 = null;
    }

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

        public void dispose() {
        }
    }

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

        public void dispose() {
        }
    }

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

        public void dispose() {

        }
    }


    public static class Stem extends Root {
        public Stem(int i) {
            super(i);
            System.out.println("Stem" + i);
        }

        @Override
        public void dispose() {
            super.dispose();
        }

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

输出

Component166
Component266
Component366
RootClass666
Stem666
Root dispose

练习13:

创建一个类,它应带有一个被重载了三次的方法。继承产生一个新类,并添加一个该方法的新的重载定义,展示这四个方法在导出类中都是可以使用的。
代码

package testPackage;

public class RootOverload {

    public void launch(int apple) {
        System.out.println("RootOverload int apple");
    }

    public static class YourLaunch extends RootOverload {
        public void launch(String banana) {
            System.out.println("YourLaunch String banana");
        }
    }

    public static class MyLaunch extends YourLaunch {
        public void launch(char pair) {
            System.out.println("MyLaunch pair");
        }
    }

    public static class HisLaunch extends MyLaunch {
        public void launch(boolean strawberry) {
            System.out.println("MyLaunch strawberry");
        }

        public static void main(String[] args) {
            HisLaunch hisLaunch = new HisLaunch();
            hisLaunch.launch(1);
            hisLaunch.launch("1");
            hisLaunch.launch('1');
            hisLaunch.launch(true);
        }
    }


}

输出

RootOverload int apple
YourLaunch String banana
MyLaunch pair
MyLaunch strawberry

练习14:

在Car.java中给Engine添加一个service()方法,并在main()中调用该方法。

is-a的关系使用继承来表达,has-a的关系则用组合来表达。

package access.local;

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

    public static class Car {
        public Engine engine = new Engine();

        public static void main(String[] args) {
            Car car = new Car();
            car.engine.service();
        }
    }
}

输出

service

练习15:

在包中编写一个类,类应具备一个protected方法。在包外部,试着调用该protected方法并解释其结果。然后,从你的类中继承产生一个类,并从该导出类的方法内部调用该protected方法。
代码

package access.foreign;

public class TestProtectedClass {
    protected void goTo() {
        System.out.println("goto");
    }
}

package access.local;

import access.foreign.TestProtectedClass;

public class PPClass extends TestProtectedClass {
    public static void main(String[] args) {
        PPClass ppClass = new PPClass();
        ppClass.goTo();
    }
}


引用

goto

练习16:

创建一个名为Amphibian的类。由此继承产生一个成为Frog的类。在基类中设置适当的方法。在main()中,创建一个Frog并向上转型至Amphibian,然后说明所有方法都可工作。

代码

package access.foreign;

public class Amphibian {

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

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

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

输出

a
b

练习17:

修改练习16,使用Frog覆盖基类中方法的定义(令新定义使用相同的方法特征签名)。留心main()中发生了什么。
代码

package access.foreign;

public class Amphibian {

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

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

        @Override
        public void a() {
            System.out.println("Frog a");
        }

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

输出

Frog a
b

练习18:

创建一个含有static final域和final域的类,说明两者间的区别。
代码

package access.local;

public class TestFinalClass {

    static final int a = 1;
    final int b;

    public TestFinalClass() {
        b = 1;
    }
    
    
}

static final 必须定义时初始化,普通final可以运行时初始化。

练习19:

创建一个含有指向某对象的空白final引用的类。在所有构造器内部都执行空白final的初始化动作。说明Java确保final在使用前必须被初始化,且一旦被初始化即无法改变。

同上。

练习20:

展示@override注解可以解决本节中的问题。

略。重写方法加此注解可以有效保证重写的正确性,会在编译期报错。

练习21:

创建一个带final方法的类。由此继承产生一个类并尝试覆盖该方法。

略。无法复写,只能重新声明新方法。

练习22:

创建一个final类并尝试继承他。

不能继承,编译器报错。

练习23:

请证明加载类的动作仅发生一次。证明该类的第一个实体的创建或者对staitic成员的访问都有可能引起加载。

练习24:

在Beetle.java中,从Beetle类继承产生一个具体类型的“甲壳虫”。其形式与现有类相同,跟踪并解释其输出结果。

代码

package access.local;

public class Insect {
    private int i;
    protected int j;

    private static int x1 = printInt("static Insect.x1 initialize.");

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

    static  int printInt(String s){
        System.out.println(s);
        return 4;
    }


}
package access.local;

import access.local.Insect;

public class Beetle extends Insect {

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

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


    public static void main(String[] args) {
        System.out.println("Beetle start main");
        Beetle beetle = new Beetle();
    }

    public static class BlueBeetle extends Beetle {
        private static int x3 = printInt("static Beetle.x3 initialized.");

        public BlueBeetle() {
            System.out.println("BlueBeetle start.");
        }

        public static void main(String[] args) {
            System.out.println("BlueBeetle start main");
            BlueBeetle beetle = new BlueBeetle();
        }
    }
}

输出

static Insect.x1 initialize.
static Beetle.x2 initialized.
static Beetle.x3 initialized.
BlueBeetle start main
i = 0j = 0
Beetle.k initialized.
k = 4
j = 0
BlueBeetle start.

加载类时,静态对象总是从最根部的父类开始,向外扩散,构造方法亦是如此。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值