2008年5月12日 星期一

SCJP - 自修重點筆記與心得 (7)

<<1-5-5>>
Enums 的宣告
  • Java 5.0中的 enum (列舉清單)可以對變數的值加以限制,只能從列舉清單中選擇某一個值。使用 enum 可以減少程式內的臭蟲。
  • enum 可以被宣告成它自己的獨立類別,或類別成員,然而它們不能被宣告在函式內!
  • 若 enum 被宣告成獨立類別,則它只能使用 public 和預設的存取等級。
  • enum 宣告後面的分號,是非必須的
  • 每一個 enum 所列舉的項目,事實上都是 enum 的實體,可以在任何 enum 型別上,藉由呼叫 value() 這個函式,一一取出 enum 的值。
  • 宣告的範例如下:
    1. 獨立類別宣告~
      enum ClothesSize {S, M, L}; //可加分號

      class Clothes {
       ClothesSize size;
      }

      public class ClothesTest {
       public static void main(String[] args) {
        Clothes goods = new Clothes();
        goods.size = ClothesSize.M;
       }
      }
    2. 類別成員宣告~
      class Clothes {
       enum ClothesSize {S, M, L} //可不加分號
       ClothesSize size;
      }

      public class ClothesTest {
       public static void main(String[] args) {
        Clothes goods = new Clothes();
        goods.size = Clothes.ClothesSize.M;
       }
      }


宣告 enum 的建構子、函式和變數
  • 事實上,enum 是一種特殊的類別,所以除了可以利用它來列舉常數之外,還可以對它增加建構子、實體變數、函式和一些被稱為常數特定類別本體(constant specific class body)的非常奇怪的東西。
  • 例:
    enum ClothesSize {
     S(32), M(34), L(36);
     //會自動呼叫傳入 int 的建構子

     ClothesSize(int no) {
      this.no = no;
     }

     private int no;
     public int getNo() {
      return no;
     }
    }

    class Clothes {
     ClothesSize size;

     public static void main(String[] args) {
      Clothes goods1 = new Clothes();
      goods1.size = ClothesSize.S;

      Clothes goods2 = new Clothes();
      goods2.size = ClothesSize.M;

      System.out.println(goods1.size.getNo()); //會印出 32
      System.out.println(goods2.size.getNo()); //會印出 34
     }
    }
  • 絕對不可以直接呼叫 enum 的建構子。enum 的建構子是根據定義在常數後面的引數,而被自動呼叫的。
  • 可以定義 enum 建構子接受多個引數,也可以對它進行多載化的動作。
  • enum 可以定義一個非常奇怪的東西,看起來就像匿名內隱類別(anonymous inner class),它被稱為常數特定類別本體(constant specific class body),當希望某個特定的常數,多載化某個 enum 所定義的函式的時候會用到。
  • 例如當大部份 size 的衣服都是印上"?",只有 L-size 的衣服是印上"!",但又不想在取得圖案的函式中加入if/then的程式碼,所以就可以讓 L 這個常數多載 getPic() 這個函式,如下:
    enum ClothesSize {
     S(32),
     M(34),
     L(36) {
      public String getPic() { //多載在 ClothesSize 定義的函式
       return "!";
      }
     };

     ClothesSize(int no) {
      this.no = no;
     }

     private int no;
     public int getNo() {
      return no;
     }
     public String getPic() {
      return "?";
     }
    }


...以上 CHAPTER 1 結束

2008年5月10日 星期六

SCJP - 自修重點筆記與心得 (6)

<<1-5-4>>
變數的宣告
Java 有兩種型態的變數:
  • 基本資料(Primitives):有 8 種,分別為 char、boolean、byte、short、int、long、double 和 float,宣告後型別無法改變。
  • 參考變數(Reference variables):是用來指涉(refer to,或存取到)到一個物件,一旦宣告成某型別後,就不能更改。一個參考變數可以用來指涉到任何其宣告型別,或宣告類別的子型別(subtype,一個相容的型別)的物件。



基本資料的宣告和範圍
  • 基本資料變數可以被宣告成是類別變數(靜態的)、實體變數、函式參數或區域變數。
  • 可在一行程式碼內同時宣告一個或多個同樣基本型別的基本資料,例:int x, y, z;。
  • 整數型態的基本型別所代表的範圍從小至大順序為:byte, short, int, long。
  • 浮點數的型態則是 double 比 float 大。
  • 數字型態都是帶有正負號的(signed),最左邊的位元(最大有效位元,the most significant digit)被用來表示正負號,1 是負號,0 是正號,其它的位元則使用二系補數表示法(two's complement notation)來表示數值。
  • 數字基本資料的範圍,只須記住前三欄即可。
    TypeBitsBytesMin. RangeMax. Range
    byte81-2727-1
    short162-215215-1
    int324-231231-1
    long648-263263-1
    float324n/an/a
    double648n/an/a
  • 多少位元可代表一個 boolean 值,是由虛擬機器決定的。
  • 一個 char 型別的變數是使用 2 Bytes(16 bits)表示,因此可儲存 unicode 字元。其實 char 是一不帶正負號的(unsigned) 16 位元的整數來表示,可存放 216 的值,範圍為 0 至 65535 (216-1)。


宣告參考變數(Reference Variables)
  • 參考變數可以被宣告成靜態變數、實體變數、函式參數或區域變數。
  • 可以在同一行程式碼內,宣告一個或多個同型別的參考變數,例:String s1, s2, s3;。


實體變數(Instance Variables)
  • 實體變數是被定義在類別內,但在任何函式之外,而且只有在一個類別被實體化的時候,才會進行被始化的動作。
  • 實體變數是屬於每個獨一無二的物件的資料欄(fields)。
  • 實體變數(Instance variable)又可稱為資料欄(field)或屬性(property/attribute)。
  • 實體變數必須知道的規則:
    1. 可使用任何四種存取等級(public, private, protected 或預設)。
    2. 可以被標示成 final, transient。
    3. 不可被標示成 abstract, synchronized, strictfp, native。
    4. 另外也不可標示為 static,因為一旦標示為 static,它就變成了類別變數(class variables,或稱靜態變數)了。
  • 區域變數、實體變數和函式的差異表(可宣告的修飾子):
    區域變數變數(非區域)函式
    finalfinal
    public
    protected
    private
    static
    transient
    volatile
    final
    public
    protected
    private
    static

    abstract
    synchronized
    strictfp
    native


區域(Local,自動 Automatic / 堆疊 Stack / 函式)變數
  • 區域變數就是宣告在函式內部的變數,非該函式的程式碼不可存取該區域變數。
  • 區域變數在函式內部開始它的生命,在函式結束時,區域變數也會被銷毀。
  • 區域變數一定是存在堆疊(stack)內,而不是在堆積(heap)內。
  • 假如該區域變數是一個物件參考,則區域變數還是存於堆疊,而這個物件就會在堆積內被建立出來。所以並沒有存在一個叫做堆疊物件(stack object)的東西,只有堆疊變數。
  • 所謂的區域物件(local object),指的是區域宣告的參考變數(local declared reference variable)。
  • 區域變數只可使用 final 修飾子。
  • 使用區域變數之前,必須先用一個值來初始化它,因為區域變數沒有預設值(實體變數有預設值)。
  • 區域變數的名稱,可以與實體變數相同,這個方法稱為遮蔽(shadowing)。當發生此情形時,該函式要存取同名稱的實體變數時,要加上 this 關鍵字,例:
    class Foo {
    int size = 27;
    public void setSize(int size) {
    this.size = size;
    }
    }


陣列宣告
  • 在 Java 中,陣列是一個物件它可以儲存數個同型別的變數,或同型別的子類別們的變數。
  • 陣列可以被用來儲存基本資料或是物件參考,但即使這個陣列是被宣告來儲存基本資料,陣列本身永遠是堆積裡的一個物件。
  • 建立一個陣列的參考變數:
    1. 宣告一個基本資料的陣列
      int[] key; //建議方式
      int key []; //合法但可讀性較低
    2. 宣告一個物件參考的陣列
      Thread[] threads; //建議方式
      Thread threads []; //合法但可讀性較低
  • 也可宣告多維陣列(multidimensional arrays),其實它就是陣列的陣列,例:
    String[][][] occupantName;//三維陣列宣告
    String[] ManagerName []; //合法的二維陣列宣告,但寫法不好
  • 在宣告陣列時同時宣告陣列的大小是不合法的,例:
    int[5] scores; //此程式碼無法編譯


Final 變數
  • 如果使用 final 這個關鍵字來宣告一個變數,一旦該變數已經被特定的值初始化了(而不是預設的),就不能再次初始化它。
  • 對於基本資料,只要讓變數被指派了一個值,就不能再被改變。
  • 對於物件參考變數(object reference variable),就是不能重新指派它去指涉到另外一個物件,不過讓物件的資料可以被修改,不能被變更的是參考變數。
  • 沒有 final 物件,只有 final 參考。
  • final 的應用意義:
  • 物件(class)final 類別不可被繼承
    函式(method)final 函式不可被子類別覆寫
    變數(variable)final 變數,一旦初始化後,就不能再指派新值


Transient 變數
  • 假如將某類別的實體變數標示成 transient,就是告訴 JVM 在序列化(serialize)包含它的物件的時候,就要忽略它。
  • 序列化是讓你可以儲存(有時候稱為”平坦化(flattern)”)物件的狀態(換句話說,該物件的實體變數的值)到一個 I/O 資料流(stream)上。使用序列化,可以將物件儲存到檔案上,或讓它在網路上傳送,並在另外一端的 JVM 上回復成原物件(再膨脹化(reinflating),反序列化(deserializing))。


Volatile 變數
  • volatile 修飾子告訴 JVM,當一個執行緒存取了該變數,必須將執行緒本身對於該變數的私自拷貝版和記憶體內的主要拷貝版進行一致化的動作。
  • volatile 就像 transient,是一個只可以應用在實體變數的修飾子。


Static 變數和函式
  • 如果類別內的某些函式或變數,和該類別的任何實體是無關的,就可以應用 static 修飾子來建立這些函式或變數。
  • 在建立任何該類別的實體之前,static 成員就已經存在了,而且不論類別有少個實體,這些 static 成員都只有一份,也就是所有實體共享同一份 static 成員。
  • 被標示成 static 的東西有:『函式』、『變數』、『一個包含在另一個類別內的類別(巢狀類別,nested),但不是在函式內的』和『初始化區塊(Initialization blocks)』。
  • 不可被標示成 static 的東西有:『建構子』、『類別』、『介面』、『函式內的區域內隱類別(method local inner classes)』、『內隱類別的函式和實體變數』和『區域變數』。

2008年5月7日 星期三

SCJP - 自修重點筆記與心得 (5)

  這幾天比較忙,所以都沒有時間看我的Java,今天又開始看了一下,以下是今日看的筆記。


<<1-5-2>>
帶有變動個數引數(Variable Argument Lists,簡稱 var-args)的函式
  • 引數與參數的用法~
    引數(arguments):當呼叫函式時,放於括號內的東西,例:doStuff("a", 2);,"a"和2即是引數。
    參數(parameters):放在函式的標記式(method's signature),用來說明這個函式呼叫時所須接收怎樣的資料,例:void doStuff(String s, int a) {},此函數預期有兩個參數,String 和 int。
  • var-args的宣告規則:
    1. var-arg 型別:可以為基本型別(primitive type)或物件型別(object type)。
    2. 基本語法:先是型別,接著是省略符號(...),加一個空白,再接著接收這參數的陣列名稱。
    3. 其他參數:使用 var-arg 的函式可以同時擁有其它參數。
    4. var-arg 的限制:var-arg 必須是函式的標記式上最後一個參數,且一個函式只能有一個 var-arg。
      例:void doStuff(char a, String... b) {}


<<1-5-3>>
建構子 (Constructor) 的宣告
  • 建構子一定不行有回傳型別!
  • 可以使用所有普通的存取修飾子,和擁有引數(包含 var-arg)。
  • 建構子的名稱一定要和類別的名子相同。
  • 建構子不可被標示為 static、final 或 abstract。