《Java编程思想》第7章练习题

源码地址:https://github.com/yangxian1229/ThinkingInJava
练习1:创建一个简单的类。在第二个类中,将一个引用定义为第一个类的对象。运用惰性初始化来实例化这个对象。

package ch7;

import static net.mindview.util.Print.*;

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; //'simple' not initialized
	}
	public void check(){
		if(simple == null)
			print("not initialized");
		else
			print("initialized");
	}
	private Simple lazy(){
		if(simple == null){
			print("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 E01 {

	public static void main(String[] args) {
		Second second = new Second("Init String");
		second.check();
		print(second.getSimple());
		second.check();
		print(second);//toString() call
		second.setSimple("New String");
		print(second);
	}

}

The Simple class has some data and methods. The Second class performs lazy initialization through the lazy( ) method, which creates (if it hasn’t been) the Simple object and then returns it. The lazy( ) method is called by all the other methods to access the Simple object.
We added print statements to show when initialization occurs, and that it happens only once.
练习2:从Detergent中继承产生一个新的类。覆盖scrub()并添加一个名为sterilize()的新方法。
练习3:略。
练习4:略。
练习5:创建两个带有默认构造器(空参数列表)的类A和类B。从A类中继承产生一个名为C的新类,并在C内创建一个B类成员。不要给C编写构造器。创建一个C类对象并观察其结果。
练习6:证明:“调用基类构造器必须是你在导出类构造器中要做的第一件事。”
练习7:修改练习5,使AB以带参数的构造器取代默认的构造器。为C写一个构造器,并在其中执行所有的初始化。
练习8:创建一个基类,它仅有一个非默认构造器;再创建一个导出类,它带有默认构造器和非默认构造器。在导出类的构造器中调用基类的构造器。
练习9:创造一个Root类,令其含有名为Component1Component2Component3的类的各一个实例。从Root中派生一个类Stem,也含有上述各“组成成分”。所有的类都应带有可打印的相关信息的的默认构造器。
练习10:修改练习9,使每个类都仅具有非默认的构造器。
练习11:修改Detergent.java,让它使用代理。
练习12:将一个适当的dispose()方法的层次结构添加到练习9的所有类中。
Remember, it’s important to call the dispose( ) methods in the reverse order of initialization.
练习13:创建一个类,它应带有一个被重载了三次的方法。继承产生了一个新类,并添加一个该方法的新的重载定义,展示这四个方法在导出类中都是可以使用的。
练习14:在Car.java中给Engine添加一个service()方法,并在main()中调用该方法。
练习15:在包中编写一个类,类应具备一个protected方法。在包外部,试着调用该protected方法并解释其结果。然后,从你的类中继承产生一个类,并从该导出类的方法内部调用该protected方法。
练习16:创建一个名为Amphibian的类。由此集成产生一个称为Frog的类。在基类中设置适当的方法。在main()中,创建一个Frog向上转型至Amphibian,然后说明所有方法都可以工作。
练习17:修改练习16,使Frog覆盖基类中的方法的定义(令新定义使用相同的方法特征签名)。请留心main()中都发生了什么。
练习18:创建一个含有static final域和final域的类,说明二者间的区别。

package ch7;

import static net.mindview.util.Print.*;

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 sscf = new SelfCounter();
	public String toString(){
		return "scf = "+scf+"\nsscf = "+sscf;
	}
}

public class E18 {
	public static void main(String[] args) {
		print("First object:");
		print(new WithFinalFields());
		print("Second object:");
		print(new WithFinalFields());
	}
}/* Output:
First object:
scf = SelfCounter 1
sscf = SelfCounter 0
Second object:
scf = SelfCounter 2
sscf = SelfCounter 0
*///:~

Because class loading initializes the static final, it has the same value in both instances of WithFinalFields, whereas the regular final’s values are different for each instance.
练习19:创建一个含有指向某对象的空白final引用的类。在所有构造器内部都执行空白final的初始化动作。说明Java确保final在使用前必须初始化,且一旦被初始化即无法改变。
练习20:展示@Override注解可以解决本节问题。
练习21:创建一个带final方法的类。由此继承产生一个类并尝试覆盖该方法。
练习22:创建一个final类并试着继承它。
练习23:请证明加载类的动作近发生一次。证明该类的第一个实体的创建或者对static成员的访问都有可能引起加载。

package ch7;

import static net.mindview.util.Print.print;

class LoadTest{
	//The static clause is executed upon class loading:
	static{
		print("Loading LoadTest");
	}
	static void staticMember(){}
}

public class E23 {
	public static void main(String[] args) {
		print("Creating an object");
		new LoadTest();
		print("Calling static member");
		LoadTest.staticMember();
	}
}/* Output:
Creating an object
Loading LoadTest
Calling static member
*///;~

Now modify the code so object creation occurs before the static member call to see that object creation loads the object. Remember, a constructor is a static method, even though you don’t define it using the static keyword.
练习24:在Beetle.java中,从Beetle类继承产生一个具体类型的“甲壳虫”。其形式与现有类相同,跟踪并解释其输出结果。

猜你喜欢

转载自blog.csdn.net/lanzijingshizi/article/details/84099147