1. 程式人生 > >【Java程式設計思想】第四版課後習題筆記

【Java程式設計思想】第四版課後習題筆記

2.11練習10:
編寫一個程式:打印出從命令列獲得的三個引數。為此,需要確定命令列陣列中string的下標。
書上的答案是:

public class E10 {
	public static void main(String[] args) {
		System.out.println(args[0]);
		System.out.println(args[1]);
		System.out.println(args[2]);
	}
} /* Output: A B C *///:~ 

但是我在Myeclipse裡面編寫之後,執行,直接就報錯了,提示下表越界了,這讓我很費解。。。。。

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
	at chart2.E10.main(E10.java:6)

然後註釋掉輸出語句,列印args.length發現長度為0????
不應該啊,這麼經典的書籍怎麼會有這麼明顯的錯誤呢?於是我開始百度這道題

然後才意識到,這裡需要使用jdk編譯執行這個檔案,然後才能輸入輸出。因為這裡我使用的是IDE編寫的,然後直接編譯運行了,根本沒有輸入引數,所以args的leng是0。找到原因之後,我用記事本檔案編寫這個類,然後直接在cmd裡面使用javac E10.java

編譯,然後執行java E10 4 5 6,這裡4 5 6 三個數是輸入的引數,可以看到程式正常輸出4 5 6了。

有些時候IDE工具確實方便,但是有時候卻無法使我們接觸到程式底層的執行過程。想弄懂這些還是需要回歸到原始的編碼方式,我慢慢的意識到大佬建議初學者使用記事本編寫程式的用意了。

這裡還可以加一個if語句,用來提示輸入三個引數。或者直接使用for迴圈輸出使用者輸入的引數

public class E10 {

	public static void main(String[] args) {
		if (args.length < 3) {
			System.out.println
("Need 3 arguments"); System.exit(1); } System.out.println(args[0]); System.out.println(args[1]); System.out.println(args[2]); } /*for (int i = 0; i < args.length; i++) { System.out.println(args[i]); }*/ }

4.9斐波那契數列
斐波那契數列是由數字1、1、2、3、5、8、13、21、34等等組成的,其中每一個數字(從第三個數字起)都是前兩個數字的和。建立一個方法,接受一個整數引數,並顯示從第一個元素開始總共有該引數所構成的所有的斐波那契數字。例如。如果執行java Fibonacci 5(其中Fibonacci是類名),name輸出應該是1、1、2、3、5

public class E09_Fibonacci {
    public static void main(String[] args) {
        int n = Integer.parseInt(args[0]);
        if (n<0){
            System.out.println("cannot use negative numbers");
            return;
        }
        for (int i=1; i <= n; i++){
            System.out.print(fi(i) + ", ");
        }
    }
    static int fi(int n){
        if (n <= 2){
            return 1;
        }
        return fi(n-1) + fi(n-2);
    }
}

4.10 吸血鬼數字
吸血鬼數字是指位數為偶數的數字,可以由一對數字相乘而得到,而這對數字包含乘積的一半位數的數字,其中從最初的數字中選取的數字可以任意排序。以兩個0結尾的數字是不允許的,例如,下列數字都是“吸血鬼”數字:
1260 = 21 * 60
1827 = 21 * 87
2187 = 27 * 81
寫一個程式,找出4位數的所有的吸血鬼數字(Dan Forhan 推薦)。

public class E10_Vampire {
    public static void main(String[] args) {
        int[] startDigit = new int[4];
        int[] productDigit = new int[4];
        for (int num1 = 10; num1 <= 99; num1++)
            for (int num2 = num1; num2 <= 99; num2++) {
                // Pete Hartley's theoretical result:
                // If x·y is a vampire number then
                // x·y == x+y (mod 9)
                if ((num1 * num2) % 9 != (num1 + num2) % 9)
                    continue;
                int product = num1 * num2;
                startDigit[0] = num1 / 10;
                startDigit[1] = num1 % 10;
                startDigit[2] = num2 / 10;
                startDigit[3] = num2 % 10;
                productDigit[0] = product / 1000;
                productDigit[1] = (product % 1000) / 100;
                productDigit[2] = product % 1000 % 100 / 10;
                productDigit[3] = product % 1000 % 100 % 10;
                int count = 0;
                for (int x = 0; x < 4; x++)
                    for (int y = 0; y < 4; y++) {
                        if (productDigit[x] == startDigit[y]) {
                            count++;
                            productDigit[x] = -1;
                            startDigit[y] = -2;
                            if (count == 4)
                                System.out.println(num1 + " * " + num2 + " : " + product);
                        }
                    }
            }
    }
}
/* Output: 
15 * 93 : 1395
21 * 60 : 1260
21 * 87 : 1827
27 * 81 : 2187
30 * 51 : 1530
35 * 41 : 1435
80 * 86 : 6880
下面這兩句我是真的沒看懂。。。。。。。。。。。。。。。。。。。。。。
productDigit[x] = -1;
startDigit[y] = -2;
*///:~ 

5.1 無參構造器
建立一個類,它包含一個未初始化的String引用。驗證該引用被初始化成了null。

public class E01_StringRefInitialization {
    String s;
    public static void main(String[] args) {
        E01_StringRefInitialization e =  new E01_StringRefInitialization();
        System.out.println("e.s = " + e.s);
    }
}
 /* Output: e.s = = null *///:~

5.1 定義時初始化和構造器初始化的區別
建立一個類,它包含一個在定義時就被初始化了的String域,以及另一個通過構造器初始化的String域。這兩種方式有何差異?

public class E02_StringInitialization {
    String s1 = "Initialized at definition";
    String s2;

    public E02_StringInitialization(String s2i) {
        s2 = s2i;
    }

    public static void main(String[] args) {
        E02_StringInitialization si = new E02_StringInitialization("Initialized at construction");
        System.out.println("si.s1 = " + si.s1);
        System.out.println("si.s2 = " + si.s2);
    }
} 
/* Output: 
si.s1 = Initialized at definition 
si.s2 = Initialized at construction 
*///:~

“The s1 field is initialized before the constructor is entered; technically, so is the s2 field, which is set to null as the object is created. The more flexible s2 field lets you choose what value to give it when you call the constructor, whereas s1 always has the same value. ”
其中s1是在建立物件之前就已經初始化了的,而s2則是建立物件時才初始化的,s2是可以隨著構造器的建立來設定不同的值,而s1則是初始化之後就不會改變的。