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