Thinking in Java 第五章习题(初始化)

练习1:创建一个类,它包含一个未初始化的String引用。验证该引用被Java初始化成了null。

class Test{
    String s;
}
public class Initialization {
    public static void main(String[] args) {
        Test t=new Test();
        System.out.println("s=: "+t.s);
    }
}

s=: null

练习2:创建一个类,它包含一个在定义时就被初始化了的String域,以及另一个通过构造器初始化的String域。这两种方式有何差异?

public class Test5_1_2 {
    public static void main(String[] args) {
        Test1 t = new Test1();
        System.out.println(t.s1+" "+t.s2);
        t.s2 = "cba";
        System.out.println(t.s1+" "+t.s2);
    }
}
class Test1{
    String s1 = "abc";
    String s2;
} 
abc null
abc cba

差别在于:
s1初始化了一次,而s2初始化了两次
s1一开始被初始化为”abc”,而s2先被初始化为null,然后再被初始化为”cba”

练习3:创建一个带默认构造器(即无参构造器)的类,在构造器中打印一条消息。为这个类创建一个对象。

class Test{
    Test(){
        System.out.println("this is a Test");
    }
}
public class Initialization {

    public static void main(String[] args) {
        Test t=new Test();
    }
}

练习4:为前一个练习中的类添加一个重载构造器,令其接受一个字符串参数,并在构造器中把你自己的信息和接受的参数一起打印出来。

class Test{
    Test(){
        System.out.println("this is a Test");
    }
    Test(String s){
        System.out.println("Test: "+s);
    }
}
public class Initialization {
    public static void main(String[] args) {
        Test t=new Test("hello");
    }
}

Test: hello

练习5:创建一个名为Dog的类,它具有重载的bark()方法。此方法应根据不同的基本数据类型进行重载,并根据被调用的版本,打印出不同类型的狗吠(barking)、咆哮(howling)等信息。编写main()来调用所有不同版本的方法。

class Dog{
    Dog(){
        System.out.println("wang wang wang");
    }
    Dog(String s){
        System.out.println(s);
    }
    Dog(int i){
        System.out.println("howling"+i);
    }
}
/**
 * Initialization
 */
public class Initialization {

    public static void main(String[] args) {
        Dog d=new Dog();
        Dog d2=new Dog("hello");
        Dog d3=new Dog(5);
    }
}

练习6:修改前一个练习的程序,让两个重载方法各自接受两个类型的不同的参数,但二者顺序相反。验证其是否工作。

class Dog{
    Dog(){
        System.out.println("wang wang wang");
    }
    Dog(int i,String s){
        System.out.println(s+" "+i);
    }
}
/**
 * Initialization
 */
public class Initialization {

    public static void main(String[] args) {

        Dog d2=new Dog("hello",5);
    }
}

结果:String不能转成int,int不能转成String

练习7:创建一个没有构造器的类,并在main()中创建其对象,用以验证编译器是否真的自动加入了默认构造器。

//: Main.java

/**
 * 默认构造器
 */

class Test {
    String s = "Hello World";
}

class Main {
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println(t.s);
    }
}
/**
 * Output:
 Hello World
 *///:~

练习8:编写具有两个方法的类,在第一个方法内调用第二个方法两次:第一次调用时不使用this关键字,第二次调用时使用this关键字——这里只是为了验证它是起作用的,你不应该在实践中使用这种方法。

//: Main.java

/**
 * 默认构造器
 */

class Test {
    private void method1() {
        System.out.println("This is method 1.");
    }
    public void method2() {
        method1();
        this.method1();
    }
 }

class Main {
    public static void main(String[] args) {
        Test t = new Test();
        t.method2();
    }
}
/**
 * Output:
 This is method 1.
 This is method 1.
 *///:~

练习9:编写机油两个(重载)构造器的类,并在第一个构造器中通过this调用第二个构造器。

//: Main.java

/**
 * 默认构造器
 */

class Test {
    Test (int t) {
        System.out.println("This is " + t);
    }
    Test (String s, int t) {
        this(t);
        System.out.println("This is " + s);
    }
 }

class Main {
    public static void main(String[] args) {
        Test t = new Test("Hello", 42);
    }
}
/**
 * Output:
 This is 42
 This is Hello
 *///:~

练习10:编写具有finalize()方法的类,并在方法中打印消息。在main()中为该类创建一个对象。试解释这个程序的行为

public class Exercise510 {

    @Override
    protected void finalize() throws Throwable {
        System.out.println("finalize() called");
    }

    public static void main(String[] args) {
        new Exercise510(); // 可能不会看到被调用的终结器,因为程序通常不会为收集器生成足够的垃圾来运行
    }
}

练习11:修改前一个练习的程序,让你的finalize()总会被调用。

public class Exercise511 {

    @Override
    protected void finalize() {
        System.out.println("finalize() called");
    }

    public static void main(String[] args) {
        new Exercise511();
        System.gc();
        System.runFinalization();
    }
}

在这里插入图片描述
练习12:编写名为Tank的类,此类的状态可以是“满的”或“空的”。
其终结条件是:对象被清理时必须处于空状态。请编写finalize()
以检验终结条件是否成立。在main()中测试Tank可能发生的几种使用方式。

class Tank {
    static int counter;
    int id = counter++;
    boolean full;
    public Tank() {
        System.out.println("Tank " + id + " created");
        full = true;
    }

    public void empty() {
        full = false;
    }

    @Override
    protected void finalize()  {
        if(full) {
            System.out.println("Error: tank " + id + " must be empty at cleanup");
        } else {
            System.out.println("Tank " + id + " cleaned up OK");
        }
    }

    @Override
    public String toString() {
        return "Tank " + id;
    }
}

public class Exercise512 {

    public static void main(String[] args) {
        new Tank().empty();
        new Tank();
        System.gc();
        System.runFinalization();
    }
}

在这里插入图片描述
练习14:编写一个类,拥有两个静态字符串域,其中一个在定义处初始化,
另一个在静态块中初始化。现在,加入一个静态方法用以打印出两个字段值。
请证明它们都会在被使用之前完成初始化动作。

public class Exercise514 {

    static String s1 = "Initialized at definition";
    static String s2;
    static {
        s2 = "Initialized in satic block";
    }

    public static void main(String[] args) {
        System.out.println("s1 = " + s1);
        System.out.println("s2 = " + s2);
    }
}

在这里插入图片描述
练习15:编写一个含有字符串域的类,并采用实例初始化方式进行初始化。

public class Exercise515 {

    String str;
    {
        str = " instance initialization";
    }
    public Exercise515() {
        System.out.println("Default constructor: " + str);
    }

    public Exercise515(String str) {
        this.str = str;
        System.out.println("constructor: " + str);
    }

    public static void main(String[] args) {
        new Exercise515();
        new Exercise515("exercise");
    }
}

在这里插入图片描述
练习16:创建一个String对象数组,并为每一个元素都赋值一个String。用for循环来打印该数组。

//: StringArray.java
import java.util.Arrays;

public class StringArray {
    public static void main(String[] args) {
        int num = 5;
        String[] sa = new String[num];
        for (int i=0; i<num; ++i) {
            sa[i] = "Girl[" + i + "]";
        }
        System.out.println(Arrays.toString(sa));
    }
}
/**
 * Output:
 [Girl[0], Girl[1], Girl[2], Girl[3], Girl[4]]
 */

练习17:创建一个类,它有一个接受一个String参数的构造器。在构造阶段,打印该参数。创建一个该类的对象引用数组,但是不实际去创建对象赋值给该数组。当运行程序时,请注意来自对该构造器的调用中的初始化消息是否打印了出来。
练习18:通过创建对象赋值给引用数组,从而完成前一个练习。

//: StringArray.java
import java.util.Arrays;

class StringExample {
    String str;
    StringExample(String str) {
        this.str = str;
        System.out.println("para = " + str);
    }

    @Override
    public String toString() {
        return str;
    }
}

public class StringArray {
    public static void main(String[] args) {
        int num = 5;
        StringExample[] sea = new StringExample[5];
        System.out.println(Arrays.toString(sea));
        for (int i=0; i<num; ++i) {
            sea[i] = new StringExample("Girl[" + i + "]");
        }
        System.out.println(Arrays.toString(sea));
    }
}
/**
 * Output:
 [null, null, null, null, null]
 para = Girl[0]
 para = Girl[1]
 para = Girl[2]
 para = Girl[3]
 para = Girl[4]
 [Girl[0], Girl[1], Girl[2], Girl[3], Girl[4]]
 */

练习19:写一个类,它接收一个可变参数的String数组。
验证你可以向该方法传递一个用逗号分隔的String列表,或是一个String[]。

public class Variable {

    Variable(String... strs){
        for(String s:strs){
            System.out.print(s+" ");
        }
    }
    public static void main(String[] args) {
        new Variable("hello","world");
        System.out.println();
        new Variable(new String[]{"haha","hehe","heihei"});
    }
}
hello world
haha hehe heihei

练习20:创建一个使用可变参数列表而不是普通的main()语法的main()。
打印所产生的args数组的所有元素,并用各种不同数量的命令行参数来测试它。

public class OtherMain {
    public static void main(String... args) {
        for (String s : args) {
            System.out.print(s + " ");
        }
        System.out.println();
    }
}
/**
 * Output:
 * haha ahah haah ahha
 *///:~

练习21:创建一个enum,它包含纸币中最小面值的6种类型。通过values()循环并打印每一个值及其ordinal()。

/**
 * TestEnum
 */
public class TestEnum {

    private enum Money{
        HUNDRED,
        FIFTY,
        TEN
    }
    public static void main(String[] args) {
        for(Money m:Money.values()){
            System.out.print(m+":"+m.ordinal()+" ");
            switch(m){
                case HUNDRED:
                    System.out.println(100);
                    break;
                case FIFTY:
                    System.out.println(50);
                    break;
                case TEN:
                    System.out.println(10);
                    break;
                default:
                    break;
            }
        }
    }
}

练习22:在前面的例子中,为enum写一个switch语句,
对于每一个case,输出该特定货币的描述。

//: TestEnum.java

/**
 * 练习使用Enum, values(), ordinal(), switch
 * Created by wang on 15/7/30.
 */
public class TestEnum {
    private enum Money {
        HUNDRED, FIFTY, TWENTY, TEN, FIVE, TWO, ONE
    }

    public static void main(String[] args) {
        for (Money m : Money.values()) {
            System.out.print(m + ":" + m.ordinal() + " ");
            switch (m) {
                case HUNDRED:
                    System.out.println("$" + 100);
                    break;
                case FIFTY:
                    System.out.println("$" + 50);
                    break;
                case TWENTY:
                    System.out.println("$" + 20);
                    break;
                case TEN:
                    System.out.println("$" + 10);
                    break;
                case FIVE:
                    System.out.println("$" + 5);
                    break;
                case TWO:
                    System.out.println("$" + 2);
                    break;
                case ONE:
                    System.out.println("$" + 1);
                    break;
                default:
                    break;
            }
        }
        System.out.println();
    }
}
/**
 * Output:
 HUNDRED:0 $100
 FIFTY:1 $50
 TWENTY:2 $20
 TEN:3 $10
 FIVE:4 $5
 TWO:5 $2
 ONE:6 $1
 *///:~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值