《寫(xiě)給大忙人看的 Java 核心技術(shù)》 02 章練習(xí)

1.改變?nèi)諝v打印程序,讓每周從周日開(kāi)始箱残。同時(shí)讓它在結(jié)尾新打印一行(并且只新打印一行)。
01題參考答案:

package com.example;

import java.time.LocalDate;

public class LearnJava {

    public static void main(String[] args) throws Exception {

        System.out.println(" Mon Tue Wed Thu Fri Sat Sun");

        final int month = 11;
        LocalDate date = LocalDate.of(2017, month, 1);

        final int dayOfWeek = date.getDayOfWeek().getValue();

        for (int i=1; i<dayOfWeek; ++i) {
            System.out.printf("%4c", ' ');
        }

        while (date.getMonthValue() == month) {
            System.out.printf("%4d", date.getDayOfMonth());
            if (date.getDayOfWeek().getValue() == 7) {
                System.out.println();
            }
            date = date.plusDays(1);
        }

        final int continueValue = (8 - date.getDayOfWeek().getValue())%7 + 7;

        for (int i=0; i<continueValue; ++i) {
            System.out.printf("%4d", date.getDayOfMonth());
            if (date.getDayOfWeek().getValue() == 7) {
                System.out.println();
            }
            date = date.plusDays(1);
        }

    }
}

01題輸出效果:

01題輸出效果

2.思考一下 Scanner 類的 nextInt 方法。它是訪問(wèn)器方法還是修改器方法掸鹅?為什么?那 Random 類的 nextInt 方法呢拦赠?

02題參考答案(個(gè)人理解):
Scanner 類的 nextInt 方法是修改器方法巍沙,因?yàn)樗淖兞?Scanner 類的狀態(tài),使其讀取下一個(gè)輸入荷鼠。Random 類的 nextInt 方法是訪問(wèn)器方法句携,因?yàn)樗皇怯脕?lái)返回隨機(jī)整數(shù),而不會(huì)改變 Random 類的狀態(tài)允乐。

3.你曾經(jīng)寫(xiě)過(guò)返回值不為 void 的修改器方法嗎矮嫉?你曾有寫(xiě)過(guò)返回值為 void 的訪問(wèn)器方法嗎?可能的話給個(gè)例子牍疏。
03題參考答案:

package com.example;

import java.util.ArrayList;

public class LearnJava {

    private static ArrayList<String> s_strings;

    // 靜態(tài)初始化塊
    static {
        s_strings = new ArrayList<>();
        s_strings.add("Mon");
        s_strings.add("Tue");
        s_strings.add("Wed");
        s_strings.add("Thu");
        s_strings.add("Fri");
    }

    // 返回值為 void 的訪問(wèn)器方法
    public void printWeekdays() {
        for (String string : s_strings) {
            System.out.printf("%4s", string);
        }
        System.out.println();
    }
    // 返回值不為 void 的修改器方法
    public boolean addSaturday() {
        if (s_strings.size() >= 5) {
            s_strings.add(5, "Sat");
            return true;
        }
        return false;
    }
    // 返回值不為 void 的修改器方法
    public boolean addSunday() {
        if (s_strings.size() >= 6) {
            s_strings.add(6, "Sun");
            return true;
        }
        return false;
    }

    public static void main(String[] args) throws Exception {

        LearnJava learnJava = new LearnJava();
        learnJava.printWeekdays();
        learnJava.addSaturday();
        learnJava.printWeekdays();
        learnJava.addSunday();
        learnJava.printWeekdays();
    }
}

03題輸出效果:

03題輸出效果

4.為什么不能實(shí)現(xiàn)一個(gè)可以交換兩個(gè) int 變量?jī)?nèi)容的 Java 方法蠢笋,但是卻可以編寫(xiě)一個(gè)交換兩個(gè) IntHolder 對(duì)象內(nèi)容的方法?(在 API 文檔中查詢這個(gè)比較晦澀的 IntHolder 類鳞陨。)你能交換連個(gè) Integer 對(duì)象的內(nèi)容嗎昨寞?

04題參考答案:
在 Java 中,所有參數(shù) —— 對(duì)象引用以及基本類型值 —— 都是值傳遞厦滤。因此援岩,不可能寫(xiě)出一個(gè)方法,將對(duì)象引用修改為其他東西掏导。我們可以查看以下的實(shí)現(xiàn)享怀,就能夠理解為何要借助 IntHolder 類來(lái)實(shí)現(xiàn)兩個(gè) Integer 變量值的交換了:

package com.example;

import org.omg.CORBA.IntHolder;

public class LearnJava {

    private Integer s_integer_a = 1;
    private Integer s_integer_b = 2;

    public void printIntegerA_B() {
        System.out.println(s_integer_a + " " + s_integer_b);
    }

    public void swapIntegerA_B() {
        int temp = s_integer_a;
        s_integer_a = s_integer_b;
        s_integer_b = temp;
    }

    public void swapIntegerA_B(Integer a, Integer b) {
        int temp = a;
        a = b;
        b = temp;
    }

    public void swapIntegerA_B(IntHolder a, IntHolder b) {
        int temp = a.value;
        a.value = b.value;
        b.value = temp;
    }

    public static void main(String[] args) throws Exception {
        LearnJava learnJava = new LearnJava();
        learnJava.printIntegerA_B();
        learnJava.swapIntegerA_B();
        learnJava.printIntegerA_B();

        Integer a = 3;
        Integer b = 4;
        System.out.println(a + " " + b);
        learnJava.swapIntegerA_B(a, b);
        System.out.println(a + " " + b);

        IntHolder c = new IntHolder(5);
        IntHolder d = new IntHolder(6);
        System.out.println(c.value + " " + d.value);
        learnJava.swapIntegerA_B(c, d);
        System.out.println(c.value + " " + d.value);
    }
}

04題輸出效果:

04題輸出效果

5.實(shí)現(xiàn)一個(gè)描述平面上點(diǎn)的不可能修改的 Point 類。提供一個(gè)設(shè)置具體點(diǎn)的構(gòu)造函數(shù)趟咆、一個(gè)設(shè)置為原點(diǎn)的無(wú)參數(shù)構(gòu)造函數(shù)添瓷,以及方法 getX梅屉、getY、translate 和 scale仰坦。translate 方法根據(jù)給定量在 x 和 y 方向上移動(dòng)該點(diǎn)履植。scale 方法根據(jù)給定因子在坐標(biāo)系按比例變化。實(shí)現(xiàn)這些方法以便它們將新的 Point 對(duì)象作為結(jié)果返回悄晃。例如:

Point p = new Point(3, 4).translate(1, 3).scale(0.5);

應(yīng)該設(shè)置 p 為坐標(biāo)系上為(2, 3.5)的點(diǎn)玫霎。

05題參考答案:

package com.example;

public class LearnJava {

    public static class Point {
        private double x;
        private double y;

        public Point(double x, double y) {
            this.x = x;
            this.y = y;
        }

        public Point() {
            this(0, 0);
        }

        public double getX() {
            return x;
        }

        public double getY() {
            return y;
        }

        public Point translate(double x, double y) {
            return new Point(this.x + x, this.y + y);
        }

        public Point scale(double s) {
            return new Point(this.x * s, this.y * s);
        }
    }

    public static void main(String[] args) {
        Point p = new Point(3, 4).translate(1, 3).scale(0.5);
        System.out.println("the point is: (" + p.getX() + "," + p.getY() + ")");
    }
}

05題輸出效果:

05題輸出效果

6.重復(fù)前面的練習(xí)5,但是使得 translate 和 scale 方法變成修改器方法妈橄。

06題參考答案:

package com.example;

public class LearnJava {

    public static class Point {
        private double x;
        private double y;

        public Point(double x, double y) {
            this.x = x;
            this.y = y;
        }

        public Point() {
            this(0, 0);
        }

        public double getX() {
            return x;
        }

        public double getY() {
            return y;
        }

        public Point translate(double x, double y) {
            return new Point(this.x + x, this.y + y);
        }

        public Point scale(double s) {
            return new Point(this.x * s, this.y * s);
        }

        public void setTranslate(double x, double y) {
            this.x += x;
            this.y += y;
        }

        public void setScale(double s) {
            this.x *= s;
            this.y *= s;
        }
    }

    public static void main(String[] args) {
        Point p = new Point(3, 4).translate(1, 3).scale(0.5);
        System.out.println("the point is: (" + p.getX() + "," + p.getY() + ")");
        p = new Point(3, 4);
        p.setTranslate(1, 3);
        p.setScale(0.5);
        System.out.println("the point is: (" + p.getX() + "," + p.getY() + ")");
    }
}

06題輸出效果:

06題輸出效果

7.給前面兩個(gè)版本的 Point 類添加 javadoc 注釋庶近。

07題參考答案:

package com.example;

public class LearnJava {

    /**
     * 一個(gè) <code>Point</code> 對(duì)象代表一個(gè)坐標(biāo)點(diǎn)
     * 坐標(biāo)點(diǎn)中包含該坐標(biāo)對(duì)應(yīng)的橫坐標(biāo)的值 x 以及縱坐標(biāo)的值 y
     * @author ZhaoDongshuang
     * @version 1.0
     */
    public static class Point {
        private double x;
        private double y;

        /**
         * 使用給定的 x 和 y 值構(gòu)造一個(gè)坐標(biāo)點(diǎn)對(duì)象
         * @param x 橫坐標(biāo)的值
         * @param y 縱坐標(biāo)的值
         */
        public Point(double x, double y) {
            this.x = x;
            this.y = y;
        }

        /**
         * 使用原點(diǎn)坐標(biāo)構(gòu)造一個(gè)坐標(biāo)點(diǎn)對(duì)象
         */
        public Point() {
            this(0, 0);
        }

        /**
         * 獲取橫坐標(biāo)的值
         * @return 返回 double 類型的橫坐標(biāo)的值
         */
        public double getX() {
            return x;
        }

        /**
         * 獲取縱坐標(biāo)的值
         * @return 返回 double 類型的縱坐標(biāo)的值
         */
        public double getY() {
            return y;
        }

        /**
         * 獲取相對(duì)原坐標(biāo)點(diǎn)移動(dòng)之后的坐標(biāo)點(diǎn),該方法不改變?cè)凶鴺?biāo)點(diǎn)的狀態(tài)
         * @param x 橫坐標(biāo)的移動(dòng)量
         * @param y 縱坐標(biāo)的移動(dòng)量
         * @return 返回移動(dòng)之后的坐標(biāo)點(diǎn)
         */
        public Point translate(double x, double y) {
            return new Point(this.x + x, this.y + y);
        }

        /**
         * 獲取相對(duì)原坐標(biāo)點(diǎn)縮放之后的坐標(biāo)點(diǎn)眷蚓,該方法不改變?cè)凶鴺?biāo)點(diǎn)的狀態(tài)
         * @param s 縮放因子
         * @return 返回縮放之后的坐標(biāo)點(diǎn)
         */
        public Point scale(double s) {
            return new Point(this.x * s, this.y * s);
        }

        /**
         * 將坐標(biāo)點(diǎn)按照給定的橫縱坐標(biāo)值進(jìn)行移動(dòng)
         * @param x 橫坐標(biāo)的移動(dòng)量
         * @param y 縱坐標(biāo)的移動(dòng)量
         */
        public void setTranslate(double x, double y) {
            this.x += x;
            this.y += y;
        }

        /**
         * 將坐標(biāo)點(diǎn)按照給定的縮放因子值進(jìn)行縮放
         * @param s 縮放因子
         */
        public void setScale(double s) {
            this.x *= s;
            this.y *= s;
        }
    }

    public static void main(String[] args) {
        Point p = new Point(3, 4).translate(1, 3).scale(0.5);
        System.out.println("the point is: (" + p.getX() + "," + p.getY() + ")");
        p = new Point(3, 4);
        p.setTranslate(1, 3);
        p.setScale(0.5);
        System.out.println("the point is: (" + p.getX() + "," + p.getY() + ")");
    }
}

8.在前面的練習(xí)中鼻种,提供的 Point 類的這些構(gòu)造函數(shù)和 getter 方法有些重復(fù)。大多數(shù) IDE 為編寫(xiě)樣板代碼都提供了快捷方式沙热。你的 IDE 都提供了哪些叉钥?

Android Studio 中在光標(biāo)選中構(gòu)造函數(shù),鍵盤快捷鍵 “alt+insert”篙贸,顯示構(gòu)造函數(shù)的快速構(gòu)建方法如下:

Android Studio 構(gòu)造函數(shù) 快速構(gòu)建方法

Android Studio 中在光標(biāo)選中某個(gè)變量投队,鍵盤快捷鍵 “alt+insert”,顯示變量的快速構(gòu)建方法如下:

Android Studio 類的變量 快速構(gòu)建方法

9.實(shí)現(xiàn)一個(gè) Car 類爵川,模擬汽車沿著 x 軸移動(dòng)敷鸦,隨著移動(dòng)消耗燃油。提供一個(gè)按照給定英里數(shù)驅(qū)動(dòng)汽車的方法寝贡、給汽車燃料箱添加給定加侖(燃油)的方法扒披,以及獲取原點(diǎn)到油位的當(dāng)前距離的方法。在構(gòu)造函數(shù)中指定燃料效率(單位為每加侖多少英里)圃泡。Car 類應(yīng)該是不可修改類嗎碟案?為什么或者為什么不應(yīng)該?

09題參考答案:

package com.example;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class LearnJava {

    public static class Car {
        private BigDecimal burningPower;
        private BigDecimal oilVolume;
        private BigDecimal miles;

        public Car(BigDecimal burningPower, BigDecimal oilVolume, BigDecimal miles) {
            this.burningPower = burningPower;
            this.oilVolume = oilVolume;
            this.miles = miles;
        }

        public Car(BigDecimal burningPower, BigDecimal oilVolume) {
            this(burningPower, oilVolume, new BigDecimal(0));
        }

        public Car(BigDecimal burningPower) {
            this(burningPower, new BigDecimal(0), new BigDecimal(0));
        }

        public void move(BigDecimal miles) {
            if (oilVolume.compareTo(miles.divide(burningPower,
                    RoundingMode.UP)) == 1) {
                this.miles = this.miles.add(miles);
            } else {
                this.miles = this.miles.add(oilVolume.multiply(burningPower));
            }
        }

        public void addOil(BigDecimal oilVolume) {
            this.oilVolume = this.oilVolume.add(oilVolume);
        }

        public BigDecimal getMiles() {
            return miles;
        }
    }

    public static void main(String[] args) {
        // 使用下面第一種方式的 2.3 初始化 BigDecimal颇蜡,其值將變成 2.2999999999999998蟆淀,
        // 所以建議使用第二種方式賦值
        // method 1
//        Car car = new Car(new BigDecimal(2.3), new BigDecimal(100));
        // method 2
        Car car = new Car(new BigDecimal("2.3"), new BigDecimal(100));
        car.move(new BigDecimal(200));

        System.out.println("Current move miles: " + car.getMiles().toString());
    }
}

09題輸出效果:

09題輸出效果

雖然我們想要這臺(tái)車開(kāi)個(gè) 400 英里,但是在當(dāng)前的燃燒率和油量下澡匪,最多只能開(kāi)到 230 英里。

10.在 RandomNumbers 類中褒链,提供兩個(gè)靜態(tài)方法 randomElement唁情,從數(shù)組或者整數(shù)數(shù)組列表中獲得隨機(jī)元素。(如果數(shù)組或者數(shù)組列表為空甫匹,則返回 0甸鸟。)為什么不能使這兩個(gè)方法成為 int [] 或 ArrayList<Integer> 的實(shí)例方法惦费?

10題參考答案:

package com.example;

import java.util.ArrayList;
import java.util.Random;

public class LearnJava {

    static class RandomNumbers {

        private static Random s_random;

        static {
            s_random = new Random();
            s_random.setSeed(System.currentTimeMillis());
        }

        public static Object randomElement(ArrayList<?> arrayList) {
            if (arrayList.size() == 0) {
                return 0;
            }
            return arrayList.get(Math.abs(s_random.nextInt())%(arrayList.size() - 1));
        }

//        public static Object randomElement(Integer[] arrayList) {
//            return randomElement(new ArrayList<>(Arrays.asList(arrayList)));
//        }

        public static Object randomElement(int[] arrayList) {
            ArrayList<Integer> intList = new ArrayList<>();
            for (Integer i : arrayList) {
                intList.add(i);
            }
            return randomElement(intList);
        }

    }

    public static void main(String[] args) {

        ArrayList<Integer> integers = new ArrayList<>();
        for (int i=0; i<100; ++i) {
            integers.add(i);
        }
        System.out.println(RandomNumbers.randomElement(integers).toString());

        int[] arrays = new int[100];
        for (int i=0; i<100; ++i) {
            arrays[i] = i;
        }
        System.out.println(RandomNumbers.randomElement(arrays).toString());
    }

}

10題輸出效果:

10題輸出效果

為什么不能使這兩個(gè)方法成為 int [] 或 ArrayList<Integer> 的實(shí)例方法?
這是因?yàn)樵?Java 中抢韭,基本類型不是類薪贫。無(wú)法創(chuàng)建其對(duì)象,即無(wú)法實(shí)現(xiàn)通過(guò)對(duì)象對(duì)方法的調(diào)用刻恭。

11.對(duì) System 和 LocalDate 類使用靜態(tài)導(dǎo)入瞧省,重寫(xiě) Cal 類。

11題參考答案:

package com.example;

import java.time.LocalDate;
import static java.time.LocalDate.of;

public class LearnJava {

    public static void main(String[] args) throws Exception {

        System.out.println(" Mon Tue Wed Thu Fri Sat Sun");

        final int month = 11;
        LocalDate date = of(2017, month, 1);

        final int dayOfWeek = date.getDayOfWeek().getValue();

        for (int i=1; i<dayOfWeek; ++i) {
            System.out.printf("%4c", ' ');
        }

        while (date.getMonthValue() == month) {
            System.out.printf("%4d", date.getDayOfMonth());
            if (date.getDayOfWeek().getValue() == 7) {
                System.out.println();
            }
            date = date.plusDays(1);
        }

        final int continueValue = (8 - date.getDayOfWeek().getValue())%7 + 7;

        for (int i=0; i<continueValue; ++i) {
            System.out.printf("%4d", date.getDayOfMonth());
            if (date.getDayOfWeek().getValue() == 7) {
                System.out.println();
            }
            date = date.plusDays(1);
        }

    }
}

11題輸出效果:

11題輸出效果

11題的示例中鳍贾,我只是使用了 of 這個(gè)靜態(tài)方法鞍匾,因此,就僅僅改動(dòng)了兩行代碼

import static java.time.LocalDate.of;
//...
LocalDate date = of(2017, month, 1);

12.創(chuàng)建一個(gè) HelloWorld.java 文件骑科,它在包 ch01.sec01 中聲明了 HelloWorld 類橡淑。把它放在某個(gè)目錄,但不在 ch01/sec01 子目錄咆爽。從存放文件的那個(gè)目錄運(yùn)行 javac HelloWorld.java梁棠。你會(huì)得到類文件嗎?類文件存放在哪里斗埂?接著運(yùn)行 java HelloWorld 會(huì)發(fā)生什么符糊?為什么?(提示:運(yùn)行 javap HelloWorld 并研究告警信息蜜笤。)最后濒蒋,為什么 javac -d . HelloWorld.java 更好?

12題參考答案:
會(huì)得到類文件把兔,文件存放在 HelloWorld.java 所在的目錄

運(yùn)行

java HelloWorld

會(huì)提示錯(cuò)誤:

錯(cuò)誤: 找不到或無(wú)法加載主類 HelloWorld

通過(guò)運(yùn)行

javap HelloWorld

我們可以知道這是因?yàn)椋?/p>

警告: 二進(jìn)制文件HelloWorld包含ch01.sec01.LearnJava

也就是無(wú)法正確的找到相應(yīng)的文件沪伙。

而使用

javac -d . HelloWorld.java

的好處是,class 文件會(huì)產(chǎn)生在單獨(dú)的目錄中县好,不會(huì)搞亂代碼樹(shù)围橡,并且 class 文件也有正確的子目錄結(jié)構(gòu)。

運(yùn)行完

javac -d . HelloWorld.java

再執(zhí)行

java ch01.sec01.LearnJava

就可以得到正常的輸出了缕贡。

13.從 http://opencsv.sourceforge.net 下載 OpenCSV 的 JAR 文件翁授。寫(xiě)個(gè)有 main 方法的類,讀取你選擇的 CSV 文件并打印部分內(nèi)容晾咪。OpenCSV 網(wǎng)站上有示例代碼收擦。我們還未學(xué)習(xí)處理異常。先用下面的內(nèi)容作為 main 方法頭:

public static void main(String[] args) throws Exception

這個(gè)練習(xí)的目的不是讓我們用 CSV 文件做些有用的事情谍倦,而是練習(xí)如何使用交付為 JAR 文件格式的類庫(kù)塞赂。

13題參考答案:

在 Android Studio 中,我們將下載的 jar 包昼蛀,放到 libs 目錄中:

放到 libs 目錄中
放到 libs 目錄之后

在 Android Studio 中宴猾,選擇需要加入 JAR 包的 java module圆存,點(diǎn)擊鼠標(biāo)右鍵:

點(diǎn)擊鼠標(biāo)右鍵

選擇 “Open Module Settings” 選項(xiàng):

選擇 “Open Module Settings” 選項(xiàng)

點(diǎn)擊新彈出的窗口的右側(cè)的 “+” 符號(hào),選擇 “jar dependency” 選項(xiàng):


選擇 “jar dependency”

在彈出的窗口中選擇我們剛剛放到 libs 中的 JAR 包:

選擇 JAR 包

下面是測(cè)試代碼(其實(shí)不好用)仇哆,只是我們可以引用 JAR 包中的方法了沦辙。

package com.example;

import com.opencsv.CSVReader;

import java.io.FileReader;
import java.util.List;

public class LearnJava {

    public static void main(String[] args) throws Exception {
        CSVReader reader = new CSVReader(
                new FileReader("/home/toby/SampleCSVFile_10600kb.csv"));

        List<String[]> myEntries = reader.readAll();
    }
}

14.編譯 Network 類。注意內(nèi)部類文件被命名為 Network$Member.class讹剔。使用 javap 程序檢查生成的代碼油讯。命令

javap -private Classname

顯示方法和實(shí)例變量。你在哪里看到外部類的引用辟拷?(在 Linux/Mac OS X 系統(tǒng)上撞羽,運(yùn)行 javap 時(shí),在 $ 符號(hào)前你需要輸入 “\”衫冻。)

14題參考答案:
我沒(méi)有編譯 Network 類诀紊,而是將第10題的例子編譯了一下:

package com.example;

import java.util.ArrayList;
import java.util.Random;

public class LearnJava {

    static class RandomNumbers {

        private static Random s_random;

        static {
            s_random = new Random();
            s_random.setSeed(System.currentTimeMillis());
        }

        public static Object randomElement(ArrayList<?> arrayList) {
            if (arrayList.size() == 0) {
                return 0;
            }
            return arrayList.get(Math.abs(s_random.nextInt())%(arrayList.size() - 1));
        }

//        public static Object randomElement(Integer[] arrayList) {
//            return randomElement(new ArrayList<>(Arrays.asList(arrayList)));
//        }

        public static Object randomElement(int[] arrayList) {
            ArrayList<Integer> intList = new ArrayList<>();
            for (Integer i : arrayList) {
                intList.add(i);
            }
            return randomElement(intList);
        }

    }

    public static void main(String[] args) {

        ArrayList<Integer> integers = new ArrayList<>();
        for (int i=0; i<100; ++i) {
            integers.add(i);
        }
        System.out.println(RandomNumbers.randomElement(integers).toString());

        int[] arrays = new int[100];
        for (int i=0; i<100; ++i) {
            arrays[i] = i;
        }
        System.out.println(RandomNumbers.randomElement(arrays).toString());
    }

}

對(duì)上述代碼所在的類文件 LearnJava.java 運(yùn)行:

javac -d . LearnJava.java

之后14題測(cè)試的效果如下:

14題測(cè)試的效果

15.完整實(shí)現(xiàn) 2.6.1 節(jié)中的 Invoice 類。提供一個(gè)打印 invoice 的方法隅俘,以及構(gòu)造并打印示例 invoice 的演示程序邻奠。

15題參考答案:

package com.example;

import java.util.ArrayList;

public class LearnJava {

    static class Invoice {
        public static class Item {
            String description;
            int quantity;
            double unitPrice;

            public Item() {
                this("", 0, 0);
            }

            public Item(String description, int quantity, double unitPrice) {
                this.description = description;
                this.quantity = quantity;
                this.unitPrice = unitPrice;
            }


            double price() {
                return quantity * unitPrice;
            }
        }

        private ArrayList<Item> items = new ArrayList<>();

        public void addItem(String description, int quantity, double unitPrice) {
            Item newItem = new Item();
            newItem.description = description;
            newItem.quantity = quantity;
            newItem.unitPrice = unitPrice;
            items.add(newItem);
        }

        public void addItem(Item item) {
            items.add(item);
        }

        public void printInvoice() {
            for (Item item : items) {
                System.out.print("description: " + item.description + ", ");
                System.out.print("quantity: " + item.quantity + ", ");
                System.out.println("unitPrice: " + item.unitPrice);
            }
        }
    }

    public static void main(String[] args) {
        Invoice invoice = new Invoice();
        invoice.addItem("Tomato", 12, 5);
        Invoice.Item item0 = new Invoice.Item("Potato", 11, 6);
        invoice.addItem(item0);

        invoice.printInvoice();
    }

}

15題輸出效果:

15題輸出效果

16.實(shí)現(xiàn)一個(gè) Queue 類 —— 一個(gè)無(wú)邊界的字符串隊(duì)列,分別提供在末尾添加字符串的 add 方法和從隊(duì)列頭部進(jìn)行刪除的 remove 方法为居。將元素存儲(chǔ)成鏈表節(jié)點(diǎn)碌宴。創(chuàng)建一個(gè)嵌套類 Node。Node 類應(yīng)該是靜態(tài)類或不應(yīng)該是靜態(tài)類嗎蒙畴?

16題參考答案:
靜態(tài)嵌套類沒(méi)有外部類的引用贰镣。當(dāng)嵌套類的實(shí)例不需要知道它屬于外部類的哪個(gè)實(shí)例時(shí),使用靜態(tài)嵌套類膳凝。只有當(dāng)這種信息重要時(shí)碑隆,才使用內(nèi)部類。

對(duì)于這個(gè)隊(duì)列來(lái)說(shuō)因?yàn)?Node 無(wú)需訪問(wèn) Queue 的成員或者方法蹬音,所以上煤,Node 可以是靜態(tài)的嵌套類。

package com.example;

import java.util.ArrayList;

public class LearnJava {

    static class Queue {

        private ArrayList<Node> nodes = new ArrayList<>();

        public static class Node {
            public String getContent() {
                return content;
            }

            private String content;

            public Node() {
                this.content = "";
            }

            public Node(String content) {
                this.content = content;
            }
        }

        public int size() {
            return nodes.size();
        }

        public void add(String value) {
            Node node = new Node(value);
            nodes.add(node);
        }

        public void remove() {
            if (nodes.size() > 0) {
                nodes.remove(0);
            }
        }

        public void printValue(int i) {
            if (i>=0 && i < nodes.size()) {
                System.out.println(nodes.get(i).getContent());
            } else {
                System.out.println();
            }
        }
    }

    public static void main(String[] args) {

        Queue queue = new Queue();

        for (int i=0; i<50; ++i) {
            queue.add(String.valueOf(i));
        }

        int i = 40;
        while (i>0) {
            queue.remove();
            --i;
        }

        for (i=0; i<queue.size(); ++i) {
            queue.printValue(i);
        }
    }

}

16題輸出效果:

16題輸出效果

17.提供一個(gè) iterator —— 依次產(chǎn)生隊(duì)列元素的對(duì)象 —— 就是上一道練習(xí)題中的隊(duì)列著淆。將 Interator 作為擁有 next 和 hasNext 方法的嵌套類劫狠。給 Queue 類提供 iterator() 方法,該方法產(chǎn)生 Queue.Iterator永部。Iterator 應(yīng)該是靜態(tài)類或不應(yīng)該是靜態(tài)類嗎独泞?

17題參考答案:

Iterator 不應(yīng)該是靜態(tài)嵌套類,因?yàn)樗枰L問(wèn)外部類的非靜態(tài)成員苔埋。

package com.example;

import java.util.ArrayList;

public class LearnJava {

    static class Queue {

        private ArrayList<Node> nodes = new ArrayList<>();

        public static class Node {
            public String getContent() {
                return content;
            }

            private String content;

            public Node() {
                this.content = "";
            }

            public Node(String content) {
                this.content = content;
            }
        }

        public class Iterator {

            private int i = -1;

            public Iterator() {
                i = -1;
            }

            public Iterator(int i) {
                this.i = i;
            }

            public Node next() {
                return nodes.get(++i);
            }

            public boolean hasNext() {
                return (i+1) < nodes.size();
            }
        }

        public int size() {
            return nodes.size();
        }

        public void add(String value) {
            Node node = new Node(value);
            nodes.add(node);
        }

        public void remove() {
            if (nodes.size() > 0) {
                nodes.remove(0);
            }
        }

        public void printValue(int i) {
            if (i>=0 && i < nodes.size()) {
                System.out.println(nodes.get(i).getContent());
            } else {
                System.out.println();
            }
        }

        public Iterator iterator() {
            return new Iterator(-1);
        }
    }

    public static void main(String[] args) {

        Queue queue = new Queue();

        for (int i=0; i<50; ++i) {
            queue.add(String.valueOf(i));
        }

        int i = 40;
        while (i>0) {
            queue.remove();
            --i;
        }

        Queue.Iterator iterator = queue.iterator();
        while (iterator.hasNext()) {
            Queue.Node node = iterator.next();
            System.out.println(node.getContent());
        }
    }

}

17題輸出效果:

17題輸出效果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末懦砂,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌孕惜,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晨炕,死亡現(xiàn)場(chǎng)離奇詭異衫画,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)瓮栗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門削罩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人费奸,你說(shuō)我怎么就攤上這事弥激。” “怎么了愿阐?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵微服,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我缨历,道長(zhǎng)以蕴,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任辛孵,我火速辦了婚禮丛肮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘魄缚。我一直安慰自己宝与,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布冶匹。 她就那樣靜靜地躺著习劫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪徙硅。 梳的紋絲不亂的頭發(fā)上榜聂,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音嗓蘑,去河邊找鬼须肆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛桩皿,可吹牛的內(nèi)容都是我干的豌汇。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼泄隔,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼拒贱!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤逻澳,失蹤者是張志新(化名)和其女友劉穎闸天,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體斜做,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡苞氮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瓤逼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笼吟。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖霸旗,靈堂內(nèi)的尸體忽然破棺而出贷帮,到底是詐尸還是另有隱情,我是刑警寧澤诱告,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布撵枢,位于F島的核電站,受9級(jí)特大地震影響蔬啡,放射性物質(zhì)發(fā)生泄漏诲侮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一箱蟆、第九天 我趴在偏房一處隱蔽的房頂上張望沟绪。 院中可真熱鬧,春花似錦空猜、人聲如沸绽慈。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)坝疼。三九已至,卻和暖如春谆沃,著一層夾襖步出監(jiān)牢的瞬間钝凶,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工唁影, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留耕陷,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓据沈,卻偏偏與公主長(zhǎng)得像哟沫,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子锌介,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353