一、创建一个简单的类。在第二个类中,将一个引用定义为第一个类的对象。运用惰性初始化来实例化这个对象。
public class Soap { private String s; Soap() { System.out.println("Soap()"); s = "Constructed"; } public void setS(String s) { this.s = s; } @Override public String toString() { return s; } } class Test { private Soap soap; public Test() { soap = new Soap(); System.out.println("init soap"); } @Override public String toString() { return soap.toString(); } public static void main(String... args) { Test test = new Test(); System.out.println(test); } }
返回:
Soap() init soap Constructed
二、 从Detergent中继承产生一个新的类。覆盖scrub()并添加一个名为sterilize()的新方法。
public 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()"); } @Override 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 { // change a method public void scrub() { append(" Detergent.scrub()"); super.scrub(); } // add methods to the interface 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); System.out.println("Testing base class:"); Cleanser.main(args); } } class Zi extends Detergent{ public void scrub() { append(" Zi.scrub()"); super.scrub(); } public void sterilize(){append(" sterilize()");} public static void main(String[] args){ Zi x = new Zi(); x.dilute();x.apply();x.scrub();x.foam();x.sterilize(); System.out.println(x); System.out.println("Testing base class:"); Detergent.main(args); } }
返回:
Cleanser dilute() apply() Zi.scrub() Detergent.scrub() scrub() foam() sterilize() Testing base class: Cleanser dilute() apply() Detergent.scrub() scrub() foam() Testing base class: Cleanser dilute() apply() scrub()
三、 证明“即使不为子类创建构造器,编译器也会合成一个默认构造器,该构造器将调用基类的构造器”。
class Art{ Art(){System.out.println("Art constructor");} } class Drawing extends Art{ public 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 cartoon = new Cartoon(); } }
编译后:
public class Cartoon extends Drawing { public Cartoon() { } public static void main(String... args) { new Cartoon(); } }
返回:
Art constructor Drawing constructor
四、证明基类构造器:a.总是会被调用;b.在导出类构造器之前被调用。
见上题
五、创建两个带有默认构造器(空参数列表)的类A和类B。从A中继承产生一个名为C的新类,并在C内创建一个B类的成员。不要给C编写构造器。创建一个C类对象并观察其结果。
class A { A(){System.out.println("A constructor");} } class B{ public B() {System.out.println("B constructor");} } public class C extends A { private B b; public static void main(String... args){ C c = new C(); } }
返回:
A constructor
六、用Chess.java来证明“调用基类构造器必须是在导出类构造器中要做的第一件事”。
七、修改练习5,使A和B以带参数的构造器取代默认的构造器。为C写一个构造器,并在其中执行所有的初始化。
class A { A(int i){ System.out.println("A constructor, i:"+i); } } class B{ B(int i) {System.out.println("B constructor, i:"+i);} } public class C extends A { private B b; C(){ super(2); System.out.println("C constructor"); b = new B(3); } public static void main(String... args){ C c = new C(); } }
返回:
A constructor, i:2 C constructor B constructor, i:3
八、创建一个基类,它仅有一个非默认构造器;再创建一个导出类,它带有默认构造器和非默认构造器。在导出类的构造器中调用基类的构造器。
class A { A(int i){ System.out.println("A constructor, i:"+i); } } public class C extends A { C(){ super(0); System.out.println("C constructor"); } C(int i){ super(i-1); System.out.println("C constructor, i:"+i); } public static void main(String... args){ C c1 = new C(); C c2 = new C(2); } }
返回:
A constructor, i:0 C constructor A constructor, i:1 C constructor, i:2
九、创建一个Root类,令其含有名为Component1、Component2、Component3的类的各一个实例。从Root中派生一个类Stem,也含有上述各“组成部分”。所有的类都应带有可打印出类的相关信息的默认构造器。
class Component1 { Component1() { System.out.println("Component1 constructor"); } } class Component2 { Component2() { System.out.println("Component2 constructor"); } } class Component3 { Component3() { System.out.println("Component3 constructor"); } } class Root { private Component1 c1 = new Component1(); private Component2 c2 = new Component2(); private Component3 c3 = new Component3(); public Root() { System.out.println("Root constructor"); } } public class Stem extends Root { private Component1 c1 = new Component1(); private Component2 c2 = new Component2(); private Component3 c3 = new Component3(); public Stem() { System.out.println("Stem constructor"); } public static void main(String[] args) { new Stem(); } }
返回:
Component1 constructor Component2 constructor Component3 constructor Root constructor Component1 constructor Component2 constructor Component3 constructor Stem constructor
十一、修改Detergent.java,让它使用代理。
class Cleanser1 { 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()"); } @Override public String toString() { return s; } } public class Detergent1 { private Cleanser1 cleanser1 = new Cleanser1(); public void dilute() { cleanser1.dilute(); } public void apply() { cleanser1.apply(); } public void scrub() { cleanser1.scrub(); } @Override public String toString() { return cleanser1.toString(); } public static void main(String[] args) { Detergent1 x = new Detergent1(); x.dilute(); x.apply(); x.scrub(); System.out.println(x.toString()); } }
返回:
Cleanser dilute() apply() scrub()
十三、创建一个类,它应带有一个被重载了三次的方法。继承产生一个新类,并添加一个该方法的新的重载定义,展示这四个方法在导出类中都是可以使用的。
class Father { public void method(){ System.out.println("method()"); } public void method(int i){ System.out.println("method(i)"); } public void method(String s){ System.out.println("method(s)"); } } public class Child extends Father{ @Override public void method(){ System.out.println("Child method()"); } public void method(boolean b){ System.out.println("method(b)"); } public static void main(String... args){ Child child = new Child(); child.method(); child.method(true); child.method(1); child.method(""); } }
返回:
Child method() method(b) method(i) method(s)
十四、 在Car.java中给Engine添加一个service()方法,并在mian()中调用该方法。
class Engine{ public void start(){} public void rev(){} public void stop(){} public void service(){System.out.println("Engine service()");} } class Wheel{ public void inflate(int psi){System.out.println("Wheel inflate(), param:["+psi+"]");} } class Window{ public void rollup(){System.out.println("Window rollup()");} public void rolldown(){} } class Door{ public Window window = new Window(); public void open(){} public void colse(){} } public class Car { public Engine engine = new Engine(); public Wheel[] wheels = new Wheel[4]; public Door left = new Door(); public Door right = new Door(); public Car(){ for (int i=0;i<4;i++){ wheels[i]=new Wheel(); } } public static void main(String... args){ Car car = new Car(); car.left.window.rollup(); car.wheels[0].inflate(72); car.engine.service(); } }
返回:
Window rollup() Wheel inflate(), param:[72] Engine service()
十五、在包中编写一个类,类应具备一个protected方法。在包外部,试着调用该protected方法并解释其结果。然后,从你的类中继承产生一个类,并从该导出类的方法内部调用该protected方法。
class Father { protected void method(){ System.out.println("method()"); } } class Other{ private Father father = new Father(); public void otherMethod(){ System.out.print("otherMethod "); father.method(); } } public class Child extends Father{ public static void main(String... args){ Child child = new Child(); child.method(); Other other = new Other(); other.otherMethod(); } }
返回:
method() otherMethod method()
十六、创建一个名为Amphibian的类。由此继承产生一个称为Frog的类。在基类中设置适当地方法。在mian()中,创建一个Frog并向上转型至Amphibian,然后说明所有方法都可工作。
class Amphibian{ void method(){ System.out.println("Amphibian method()"); } } public class Frog extends Amphibian { public static void main(String... args) { // 子类向上转型为基类 Amphibian frog = new Frog(); frog.method(); } }
返回:
Amphibian method()
十七、修改十六,使Frog覆盖基类中方法的定义(令新定义使用相同的方法特征签名)。请留心main()中都发生了什么。
class Amphibian{ void method(){ System.out.println("Amphibian method()"); } } public class Frog extends Amphibian { @Override void method() {System.out.println("Frog method()");} public static void main(String... args) { Amphibian frog = new Frog(); frog.method(); } }
返回:
Frog method()
十八、创建一个含有static final域和final域的类,说明二者间的区别。
注:类初始化的时候就已经决定了NUM_1的值,而且全局唯一;而num2是在初始化对象的时候赋值的,一个对象一个值。
public class FinalData { private static final int NUM_1; private final int num2; static { NUM_1 = new Random(47).nextInt(); System.out.println("NUM_1:"+NUM_1); } public FinalData(int num2) { this.num2 = num2; System.out.println("NUM_1:"+NUM_1+", num2:"+num2); } public static void main(String... args) { FinalData finalData1 = new FinalData(1); FinalData finalData2 = new FinalData(2); } }
返回:
NUM_1:-1172028779 NUM_1:-1172028779, num2:1 NUM_1:-1172028779, num2:2