Java 程式設計()  第 七章 類別與物件產生  上一頁    下一頁

 

7-5 靜態變數的應用

內容:

  • 7-5-1 類別變數 - static

  • 7-5-2 範例研討:智慧型庫存管理系統

  • 7-5-3 範例研討:停車場管理系統

7-5-1 類別變數 - static

基本上,經由類別產生若干個物件後,各個物件都屬獨立性個體,有自己的記憶體空間、變數成員與方法成員。但某些情況下,我們還是希望同一類別所產生的物件們,之間保留有一些連帶關係。讓物件之間保留關係,最簡單的方法的讓物件之間享有共同的變數成員,此型態變數稱為『靜態變數』(Static variable)或『類別變數』(Class variable)。類別實體內宣告某一個靜態變數(如 static int a;)之後,無論該類別產生多個物件(如 xyz...等),靜態變數都指向同一變數(如 x.ay.az.a);也就是說,改變任一物件的靜態變數(如 x.a)的內容,則其他靜態變數的內容也隨之改變(如 y.a z.a);如圖 7-8 所示。

7-12 靜態變數的特性

靜態變數的宣告語法如下:

class product {

   …..

   static int total;

}

重點說明如下:

(1) 宣告類別變數必須加入 static 關鍵字

(2) 類別變數同樣具有 publicprivate protected 屬性。

(3) 宣告範例如下:public static int aprivate static String name...等。

7-5-2 範例研討:智慧型庫存管理系統

A)程式功能:Ex7_2.java

許多經理人都想盡辦法降低庫存量與增加銷售量,來增加公司的獲利,但兩者其實互相衝突。當庫存量不足時,可能會嚴重影響到銷售的順暢性,庫存量太高則會積壓公司資金,如何掌握最恰當的庫存量,實為考驗經理人能力的關鍵,最簡單的方法是隨時掌握目前庫存金額多寡。因此,『春嬌超商連鎖公司』期望建立一套智慧型的庫存管理系統。

該系統允許選擇商品及進貨或出貨數量,進貨用正號(如 +10);出貨用減號(如 -10)。庫存檔案儲存於 product.data 內,每一商品包含四個欄位:{品名、單價、庫存量、金額、總庫存金額}(如 可口奶滋 ),其中 "金額" 為該項產品庫存金額。"總庫存金額" 為所有庫存量的總金額;進出任何商品後,總庫存金額會登錄目前所有金額多寡。除了能滿足一般庫存系統的功能外,也能讓經理人隨時了解目前庫存金額多寡。期望操作介面如下:

D:\Java2_book\chap7\Ex7_2>javac Ex7_2.java

 

D:\Java2_book\chap7\Ex7_2>dir/b

Ex7_2.class                               【主程式類別】

Ex7_2.java                               【主程式檔案】

Product.class                              【產品類別】

Product.data                              【產品資料檔案】

 

D:\Java2_book\chap7\Ex7_2>java Ex7_2

**** 未登錄前庫存量 ***

品名            單價    庫存量  金額    總庫存金額

可口奶滋        20      50      1000    2780

黑松汽水        12      40      480     2780

味全鮮乳        15      50      750     2780

頻果西打        8       80      640     2780

 

(1) 可口奶滋    (2) 黑松汽水    (3) 味全鮮乳    (4) 頻果西打

        請輸入貨品編號(或大於 5 離開) =>4

         進出貨數量 =>20

品名            單價    庫存量  金額    總庫存金額

可口奶滋        20      50      1000    2940

黑松汽水        12      40      480     2940

味全鮮乳        15      50      750     2940

頻果西打        8       100     800     2940

總庫存金額(product.total) = 2940

B)製作技巧研討:

吾人將 Product 類別中庫存總金額宣告成類別變數(static int total;),當任何一樣產品變更此內容時,所有產品的 total 值隨之改變。因此,查閱任何一筆資料都可以知道目前總庫存金額多寡。

接著,吾人必須利用編輯工具( notepad ++) 建立一個 product.data 庫存資料檔,如下圖所示。進入系統後,它讀取庫存資料。

D:\Java2_book\chap7\Ex7_2>type product.data

可口奶滋        20      50      1000    2780

黑松汽水        12      40      480     2780

味全鮮乳        15      50      750     2780

頻果西打        8       80      640     2780

C)程式範例:

7-13 Ex7_2 程式架構

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

//Ex7_2.java

 

import java.io.*;

import java.util.Scanner;

class Product {

     String name;          //產品名稱

     int price;            // 單價

     int storage;          // 庫存量

     int deposit;           // 金額

     static int total;     // 庫存總金額(類別變數)

}

 

public class Ex7_2 {

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

       Product[] article = new Product[20];

       Scanner keyin=new Scanner(System.in);

       String file = "Product.data";

       String inData;

       int k=0, select, count;

       File fileID = new File(file);

       if (fileID.exists()) {

           BufferedReader data = new BufferedReader(new

                                       FileReader(fileID));

           while ((inData=data.readLine()) != null) {

               Scanner s = new Scanner(inData).useDelimiter("\t");

               article[k] = new Product();

               article[k].name = s.next();

               article[k].price = s.nextInt();

               article[k].storage = s.nextInt();

               article[k].deposit = s.nextInt();

               article[k].total = s.nextInt();

               k = k +1;

           }

           data.close();

      }

      else{

           System.out.printf("%s file not existed\n", file);

           return;

      }

      System.out.printf("**** 未登錄前庫存量 ***\n");

      System.out.printf("品名\t\t單價\t庫存量\t金額\t總庫存金額\n");

      for (int i=0; i<k; i++) {

          System.out.printf("%s\t%d\t%d\t%d\t%d\n", article[i].name,

article[i].price, article[i].storage,

article[i].deposit, article[i].total);

      }

      System.out.printf("\n");

      for (int i=0; i<k; i++)   

          System.out.printf("(%d) %s\t", i+1, article[i].name);

      System.out.printf("\n");

      System.out.printf("\t請輸入貨品編號(或大於 5 離開) =>");

      select = keyin.nextInt();

      if (select < 5) {

          System.out.printf("\t 進出貨數量 =>");

          count = keyin.nextInt();

          int s1 = select-1;

          int m1 = article[s1].price * count;

          article[s1].storage = article[s1].storage + count;

          article[s1].deposit = article[s1].deposit + m1;

          article[s1].total = article[s1].total + m1;

      }

      System.out.printf("品名\t\t單價\t庫存量\t金額\t總庫存金額\n");               

      for (int i=0; i<k; i++) {

          System.out.printf("%s\t%d\t%d\t%d\t%d\n", article[i].name,

                              article[i].price, article[i].storage,

                              article[i].deposit, article[i].total);

      }

      System.out.printf("總庫存金額(product.total) = %d\n", Product.total);

  }

}

D)程式重點分析

(1) 21~40 :系統啟動後,立即將 Product.data 檔案內所儲存的庫存資料讀入,並儲存於 article[] 物件陣列內,其中利用變數 k 紀錄有多少筆資料。

(2) 41~48 :將 article[] 陣列內容顯示於螢幕上。

(3) 49~51 :將陣列 article[] 內每一筆資料的產品名稱(article[i].name)印出,讓操作者選擇登錄哪一樣產品。

(4) 53~63 :計算操作者所登錄產品的進出貨。

(5) 64~71 :輸出登錄後的庫存資料。

7-5-3 範例研討:停車場管理系統

A)程式功能:Ex7_3.java

 高雄市政府公告『前金立體停車場管理系統』招標事項,該系統需具有下列功能:(假設範例)

(1) 顯示目前停車車輛:顯示目前每部車子的停車票號碼與進場時間。

(2) 車輛進入取票:車輛進入停車場時,會給予車子一個停車票,其中包含停車票號碼與進場時間。停車號碼由 1 開始累增。

(3) 車輛出場繳費:車輛離開時,需繳交停車票;系統搜尋該車輛紀錄時間,並計算停車費用(每 30 分鐘 20 元)。

(4) 還未安裝計時時鐘,時鐘的時間由人工輸入設定。

參與投標者須建立一套模擬系統,除了可提供上述功能之外,為增加現場臨場感,需增加一項設定目前時間的功能,作為計算停車費的依據。期望雛型模擬系統具有下列操介面:

(1) 編譯後,正常執行如下:

D:\Java2_book\chap7\PM7_1>javac Customer.java    【編譯 Customer.java

D:\Java2_book\chap7\PM7_1>javac PM7_1.java      【編譯 PM7_1.java

D:\Java2_book\chap7\Ex7_3>javac carTicket.java     【編譯 carTicket.java

D:\Java2_book\chap7\Ex7_3>javac Ex7_3.java        【編譯 Ex7_3.java

 

D:\Java2_book\chap7\Ex7_3>dir/b       【產生相關檔案 4 個類別】

Cars.class                                    【停車場車輛物件】

carTicket.class                                【停車票物件】

carTicket.java

Clock.class                                   【公用計時物件】

Ex7_3.class                                   【主類別】

Ex7_3.java

(2) 主選單有 5 個選項,選項 1 為顯示目前停車場各輛車的進場時間、選項 2 為模擬計時器,利用人工輸入目前時間、選項 3 是車輛進入停車場,取票與開始計時、選項 4 是車輛離開時,繳費與刪除,如下:

D:\Java2_book\chap7\Ex7_3>java Ex7_3

** 高雄市前金立體停車場 管理系統 目前時間 0 0 **

(1) 顯示目前停車      (2) 設定目前時間

(3) 車輛進入取票      (4) 車輛出場繳費

(5) 離開系統

目前車輛 0 請輸入工作選項 =>

(3) 首先設定目前時間(選項 2),如設定目前時間是 8 20 分,如下:

目前車輛 0 請輸入工作選項 =>2

請輸入目前時間(/) =>08/20

 

** 高雄市前金立體停車場 管理系統 目前時間 8 20 **

(1) 顯示目前停車      (2) 設定目前時間

(3) 車輛進入取票      (4) 車輛出場繳費

(5) 離開系統

(4) 當車輛進入時,會自動產生停車號碼,與登錄當時時間,如下:

目前車輛 0 請輸入工作選項 =>3

請按<Enter>鍵取票 (票號:1) =>

(5) 如進入 3 輛車後,顯示目前停車場車輛(選項 1),如下:

目前車輛 3 請輸入工作選項 =>1

停車票號                進入時間

1               8 20

2               9 10

3               9 40

 

** 高雄市前金立體停車場 管理系統 目前時間 9 40 **

(1) 顯示目前停車      (2) 設定目前時間

(3) 車輛進入取票      (4) 車輛出場繳費

(5) 離開系統

目前車輛 3 請輸入工作選項 =>

(6) 2 號車欲離開時,其操作如下(選項 4)

目前車輛 3 請輸入工作選項 =>4

請出示停車票 =>2

請繳交 20 停車費(<Enter>) =>

 

** 高雄市前金立體停車場 管理系統 目前時間 9 40 **

(1) 顯示目前停車      (2) 設定目前時間

(3) 車輛進入取票      (4) 車輛出場繳費

(5) 離開系統

目前車輛 2 請輸入工作選項 =>

B)製作技巧提示:

製作此系統時需考慮車輛進出口並不一定會相同,即是系統可能由:入口(車輛進入取票功能)、出口(車輛出場繳費功能)、與管理處(顯示目前停車功能)等 3 個地方同時操作。因此需將儲存停車資料檔案設定成共享資料,為了方便系統設計,我們採用物件導向設計理念,圖 7-9 為資料流程概念圖。首先我們宣告停車票類別(carTicket),描述每張停車票的內容:ticket enterTime[2],前者為停車票號碼、後者為車輛進場時間(時與分)。另外,製作一個停車票紀錄類別 Cars,期望它是共用屬性,因此宣告成靜態類別,所有程式都可直接存取。Cars 類別包含:car[] number,前者紀錄每張停車票的資料,後者紀錄目前停車場的車輛數目。本系統也須設定一個靜態時間類別 Clock,紀錄目前時間。

7-14 範例 Ex7_3 資料流程

C)相關類別設計(carTicket.java

依照上述的規劃,我們需要 3 個類別,將其製作於 carTicket.java 檔案,編譯後會分別產生下列 3 個類別檔案(如圖 7-9 所示),功能如下:

(1) carTicket.class:停車票類別。功能是記錄停車票號碼,以及車輛進場時間;成員如下:

(a) int setTicket():設定停車票號碼的方法。

(b) int getTicket():取得停車票號碼的方法。

(c) enterTime[]:儲存車輛進入時間的變數,可任意存取。

(2) Cars.class:儲存停車票的類別變數,包含有:

(a) static carTicket[] car:進入車輛的停車票記錄(靜態變數)。由此記錄可知該車輛何時進入停車場,可做收費的依據。

(b) static int number:紀錄目前停車場的車輛數(靜態變數)。

(3) Clock.class:主時鐘的類別變數。記錄目前時間,包含有:

(a) Static int clock:目前幾點鐘(時數,靜態變數)。

(b) Static int minute:目前幾分鐘(分鐘數,靜態變數)。

(4) carTicket.java 原始檔案如下所示:

7-15 carTicket.java 程式架構

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

//carTicket.java

 

/* 停車票  */

class carTicket {

    private static int count=0;

    private int ticket;       // 停車票號碼

    int[] enterTime = new int[2];      // 進入停車場時間

   

    int setTicket() {                 // 設定停車票號碼

        count++;

        ticket = count;

        return ticket;

    }

    int getTicket() {                 // 取得停車票號碼

        return ticket;

    }

}

/* 目前停放車輛 */

class Cars {

    static carTicket[] car = new carTicket[100];

    static int number;

}

/*公眾計時器 (利用設定輸入) */

class Clock {

     static int hour;

     static int minute;

}

D)主程式範例(Ex 7_3.java

7-16 Ex7_3 程式架構

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

//Ex7_3.java

/* 請建立一套停車場管理系統,功能有:顯示目前停車車輛、

   車輛進入取票、車輛出場繳費 */

 

import java.io.*;

import java.util.*;

public class Ex7_3 {

    static Scanner keyin = new Scanner(System.in);

    public static void main(String args[]) {

         Cars.number = 0;

         int select = get_menu();

         while (select != 5) {

             switch(select) {

                  case 1:       // 顯示目前停車

                       disp_cars();

                       break;

                  case 2:      // 設定現在時間

                       set_time();

                       break;

                  case 3:       // 車輛進入

                       enter_car();

                       break;

                  case 4:          // 車輛出場

                       outer_car();

                       break;

                  default:

                       System.out.printf("錯誤選擇, 請重新輸入\n");

             }

             select = get_menu();

         }

    }

 

    /* 主功能表選單 */

    static int get_menu()  {

        System.out.printf("\n** 高雄市前金立體停車場 管理系統 目前時間");

        System.out.printf(" %d %d **\n", Clock.hour, Clock.minute);

        System.out.printf("(1) 顯示目前停車      (2) 設定目前時間\n");

        System.out.printf("(3) 車輛進入取票      (4) 車輛出場繳費\n");

        System.out.printf("(5) 離開系統\n");

        System.out.printf("目前車輛 %d 請輸入工作選項 =>", Cars.number);

        int select = keyin.nextInt();

        keyin.nextLine();

        return select;

    }

 

    /* 顯示目前停車車輛 */

    static void disp_cars() {

        System.out.printf("停車票號\t\t進入時間\n");

        for(int i=0; i<Cars.number; i++) {

            System.out.printf("%d\t\t", Cars.car[i].getTicket());

            System.out.printf("%d %d \n", Cars.car[i].enterTime[0],

                           Cars.car[i].enterTime[1]);

        }

    }

 

    /* 設定目前公用時間 */

    static void set_time() {

        System.out.printf("請輸入目前時間(/) =>");

        String now = keyin.nextLine();

        Scanner s = new Scanner(now).useDelimiter("/");

        Clock.hour = s.nextInt();

        Clock.minute = s.nextInt();

    }

 

    /* 車輛進場 */

    static void enter_car() {

         Cars.car[Cars.number] = new carTicket();

         Cars.car[Cars.number].setTicket();

         Cars.car[Cars.number].enterTime[0] = Clock.hour;    //記錄時

         Cars.car[Cars.number].enterTime[1] = Clock.minute;    // 記錄分

         int ticket = Cars.car[Cars.number].getTicket();

         System.out.printf("請按<Enter>鍵取票 (票號:%d) =>", ticket);

         keyin.nextLine();

         Cars.number = Cars.number + 1;               // 下一輛號碼

     }

 

     /* 車輛出場, 繳費 */

     static void outer_car() {

         System.out.printf("請出示停車票 =>");

         int ticket = keyin.nextInt();

         keyin.nextLine();

         int flag =0, i;

         for(i=0; i<Cars.number; i++) {            // 搜尋該停車號

             if(ticket == Cars.car[i].getTicket()){

                 flag = 1;

                 break;

             }

         }

         if (flag == 0) {

            System.out.printf("查無此車輛 \n");

            return;

        }

        int hour = Clock.hour - Cars.car[i].enterTime[0];

        int minute = Clock.minute - Cars.car[i].enterTime[1];

        minute = minute + hour * 60;

        int tax = (minute/30) * 20;

        for(int j=i; j<Cars.number; j++)       // 刪除該車票紀錄

             Cars.car[j] = Cars.car[j+1];

        Cars.number = Cars.number - 1;         // 停車數 - 1

        System.out.printf("請繳交 %d 停車費(<Enter>) =>", tax);

        keyin.nextLine();

    }

}

 

翻轉工作室:粘添壽

 

Java 程式設計(二) 含物件導向

 

 

翻轉電子書系列: