顯示具有 Java 標籤的文章。 顯示所有文章
顯示具有 Java 標籤的文章。 顯示所有文章

2014年8月28日 星期四

透過 Eclipse 設定 VM arguments

        之前在這篇文章中提到透過 Boloean.getBoolean("TRUE") 總是回傳 false, 是因為我們沒有設定額外的系統參數給 JVM,除了你可以在程式中透過 System.setProperty("TRUE", "TRUE"); 設定讓 getBoolean 方法回傳 true 外,你還可以自己透過在執行你的 Java 程式時設定,如下畫面:

        如果是使用 Eclipse IDE 來編譯/執行 你的 Java 程式,你可以透過 "Run Configurations..." 來設定你的 JVM 系統參數,設定方式如下圖示:

圖一

圖二
     範例程式如下:

 
package com.josh.demo;

public class GetBooleanDemo {
  public static void main(String[] args) {
   System.out.println("getBoolean(\"TRUE\") = " + Boolean.getBoolean("TRUE"));
   System.out.println("getBoolean(\"FALSE\") = " + Boolean.getBoolean("FALSE"));
   System.out.println("getBoolean(\"True\") = " + Boolean.getBoolean("True"));
   System.out.println("getBoolean(\"False\") = " + Boolean.getBoolean("False"));
 }
}

2013年12月2日 星期一

列印例外訊息 printStackTrace()、toString()、 getMessage()

     當我們處理 Java 例外時,通常會在例外捕獲時列印例外的訊息,一般在輸出訊息通常使用 printStackTrace()、toString()、 getMessage() 這三種方法列印出例外訊息。
     而輸出訊息的格式請參考下面圖示:

  • printStackTrace ()方法 輸出如下
  • java.io.FileNotFoundException: abc.txt (系統找不到指定的檔案。)
     at java.io.FileInputStream.open(Native Method)
     at java.io.FileInputStream.<init>(Unknown Source)
     at java.io.FileInputStream.<init>(Unknown Source)
     at ExceptionExample.someMethod(ExceptionExample.java:7)
     at ExceptionExample.main(ExceptionExample.java:19)
    
  • toString()方法 輸出如下
  • java.io.FileNotFoundException: abc.txt (系統找不到指定的檔案。)
    
  • getMessage()方法 輸出如下
  • abc.txt (系統找不到指定的檔案。)
    
    另外我們故意讓程式丟出 NullPointerException,透過上面三種方法輸出例外訊息,其範例與輸出結果如下:
  • 範例
  •     String str = null;
        try {
             str.length();
        } catch (Exception e) {
             e.printStackTrace();
        }
    
  • printStackTrace()
  • java.lang.NullPointerException
     at ExceptionExample.main(ExceptionExample.java:30)
    
  • toString()
  • java.lang.NullPointerException
    
  • getMessage()
  • null
    
     在上面的 NullPointerException 例子,toString() 與 getMessage() 幾乎沒有任何幫助,基本上,除非是自訂的例外或者可以明顯知道例外的輸出的解果發生在哪個地方,例如,我們只在某個地方開啟特殊的檔案,則我們可以考慮使用  toString() 與 getMessage() 來減少除錯訊息的輸出,否則建議還是直接 printStackTrace() 方法輸出詳細的例外訊息。

[參考資料]




2013年12月1日 星期日

String equals( ) 與 compareTo( ) 方法的不同

     Java 中要比對字串是否相等,我們可以使用 equals 或者 compareTo 方法來實現,但是它們之間有甚麼不同呢 ? equals 與 compareTo 之間主要的不同有下面兩點:

  1. 如果傳入的參數是 null 時, equals  總是回傳 false,而 compareTo 則是丟出 java.lang.NullPointerException。
    範例如下:
     "foo".equals((String)null)  // 回傳 false
     "foo".compareTo((String)null) == 0 // 丟出 NullPointerException
    

  2. compareTo 除了可以比對字串是否相等外,還可以得知哪一個字串比較大或者小,equals 只能比對是否相等。
     另外好奇的是,為何將 null 傳入 equals 裡面會沒事,看了一下原始碼你會發現類似下面的程式碼:
   if (anObject instanceof String) {
      ...  
   }
    而 null 是物件的參考常數值,它可以被任何物件所參考,但它不屬於任何物件。也就是說 null instanceof object 總是回傳 false,故在將它傳入 equals method 並不會丟出任何例外。

    下面是從 Oracle 上查詢到的資料,解釋有關 null type。有興趣的人可以連結過去查看。
4.1. The Kinds of Types and Values
There is also a special null type, the type of the expression null (§3.10.7, §15.8.1), which has no name.
Because the null type has no name, it is impossible to declare a variable of the null type or to cast to the null type.
The null reference is the only possible value of an expression of null type.
The null reference can always undergo a widening reference conversion to any reference type.
In practice, the programmer can ignore the null type and just pretend that null is merely a special literal that can be of any reference type.   

2013年11月17日 星期日

透過 getenv 與 getProperties 取得系統環境變數與JVM屬性設定

      在 Java 中我們可以透過 System.getProperties() 取得 JVM 參數設定System.getenv() 來取得作業系統的環境變數設定。你可以在 The Java Tutorials 裡面參考 System Properties 與 Environment Variables 教學文章看到其他用法。

     如果你使用 Eclipse 你可以透過 -D<Key>=<Value> 的方式在 Run > Run Configurations... > (x)= Arguments > VM Arguments 來設定額外的 JVM 屬性設定。例如你可以填入 -DColor=blue 來設定 Color 屬性為 blue。如下圖所示:


簡易的範例程式如下:
    // 列出目前所有的 JVM 屬性設定
    System.getProperties().list(System.out); 
    
    // 透過 getProperty 單獨取出特定的某個屬性設定值    
    System.out.println("Color = " + System.getProperty("file.separator"));    

    // 取出我們設定的屬性值,注意屬性名稱是 case sensitive
    // 如果你寫成 color 得到的會是 null
    System.out.println("Color = " + System.getProperty("Color"));

    // 你也可以使用下列方式,當所指定的屬性沒有鍵值時,回傳你所設定的預設值
    // 下面的範例當沒有設定 Color 屬性鍵值時會回傳預設的 Pink 值
    System.out.println("Color = " + System.getProperty("Color", "Pink")); 

    // 列出目前作業系統所有的環境變數設定
    Set<Map.Entry<String, String>> envSet = System.getenv().entrySet();
    for (Map.Entry<String, String> set: envSet) {
        System.out.println(set.getKey() + " = " + set.getValue());
    }
    // 透過 System.getenv(key) 的方式單獨取出你想要的屬性設定
    System.out.println("SystemDrive = " + System.getenv("SystemDrive"));
    System.out.println("TEMP = " + System.getenv("TEMP"));


參考文章:



2013年11月13日 星期三

保護回傳參考型態的物件

      今天在 "最新 Java 7 程式語言 施威銘" 這本書中看到了一篇內容,大概的內容是講述當我有一個類別 Circle, 該類別裡面包含了另一個類別 Point 物件紀錄 Circle 的中心點,為了保護 Point 物件,所以在 Circle 裡面使用 private 來修飾 Point 物件;但當外部需要取得中心點資料時,便在 Circle 類別寫了一個傳回 Point 的參考物件 method,此時因為外部可以取得 Point 的物件參考,所以外部就可透過 所得到的 Point 物件參考來設定修改資料,這樣就違背了當初我們不想讓外部的使用者來隨便設定 Circle 的中心點的用意,也失去了把 Point 設成 private 作用。
     所以為了避免這種情況發生,可以使用下列方式:
  1. new 一個新的 Point 物件,拷貝目前 Circle 物件內的 Point 物件資料。
  2. 將 Point 變成 immutable 的類別,也就是不提供設定(setXX ) method。
  3. Point 類別 implements Cloneable 類別,然後回傳 clone 物件。
    書本使用第一個方式,在回傳 Point 物件參考的 method 中,可以先用 new 的方式將目前在 Circle 類別內的 Point 物件拷貝一份,然後傳回去。這樣外部修改 Point 物件時就不會影響原本的 Circle 物件裡 Point 物件資料了。

範例程式:

class Point implements Cloneable {
    private int x;
    private int y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    // 2. 把 setPoint 移除,讓 Point 變成 immutable 的類別
    public void setPoint(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public int getX() {
        return x;
    }
    public int getY() {
        return y;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Circle {
    private Point point;
    private int radius;
    public Circle(int x, int y, int r) {
        point = new Point(x, y);
        radius = r;
    }
    public Point getPoint() {
        return point;
    }
    public Point getReadOnlyPoint() {
        try {
            // 3. 讓 Point 類別實作 Cloneable,然後回傳 clone 物件 
            return (Point)point.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
    public Point getReadOnlyPoint2() {
        //1. 使用 new 的方式,將目前的Point 資料拷貝一份
        return new Point(point.getX(), point.getY());
    }
    
    @Override
    public String toString() {
        return String.format("(%d, %d) ,radius = %d", point.getX(), point.getY(), radius);
    }
}

public class ProtectReferenceObj {
    public static void main(String[] args) {
        Circle circle = new Circle(1,1,2);
        Point pt = circle.getPoint();
        System.out.println("Before: " + circle);
        pt.setPoint(10, 20);
        System.out.println("After: " + circle);
        System.out.println("================================");
        System.out.println("Before: " + circle);
        Point pt2 = circle.getReadOnlyPoint();
        pt2.setPoint(11, 22);
        System.out.println("After: " + circle);
        System.out.println("pt2.x =  " + pt2.getX() + " pt2.y = " + pt2.getY());
        System.out.println("================================");
        System.out.println("Before: " + circle);
        Point pt3 = circle.getReadOnlyPoint2();
        pt3.setPoint(55, 99);
        System.out.println("After: " + circle);
        System.out.println("pt3.x =  " + pt3.getX() + " pt3.y = " + pt3.getY());
    }
}


輸出結果:
Before: (1, 1) ,radius = 2
After: (10, 20) ,radius = 2
================================
Before: (10, 20) ,radius = 2
After: (10, 20) ,radius = 2
pt2.x =  11 pt2.y = 22
================================
Before: (10, 20) ,radius = 2
After: (10, 20) ,radius = 2
pt3.x =  55 pt3.y = 99


2013年11月5日 星期二

ArrayList 使用 toarray 轉換成物件陣列

     在某些情況下,我們希望能夠將 ArrayList 物件所存的內容轉換成陣列的形式,在 ArrayList 中提供了 toarray 方法來達到我們的需求。下面是 Java 所提供的 toarray 方法的原始碼:

    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

    public T[] toArray(T[] a) {
        if (a.length < size)
            // Make a new array of a's runtime type, but my contents:
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }

     有上面可知,我們有兩個方式可以使用 toarray 方法,一個是不帶任何參數 toarray 方法回傳 Object 陣列,另外一個是回傳你所傳入的型態陣列。
     我們先來看 public T[] toArray(T[] a) 的方法,從原始碼中,我們發現此方法會使用參數的 length 的屬性,代表該參數必須要先配置過記憶體才行,如果直接傳 null 給它會引發 "java.lang.NullPointerException" 的例外事件。再回頭看一下原始碼,會發現當你所配置的陣列元素小於目前 ArrayList 所儲存的元素時,toarray 方法會幫你配置足夠的元素來儲存目前 ArrayList 物件中所含的所有元素。而當你的所配置的陣列元素個數大於目前會將你所配置的第 size 元素設定為null。基本上你可以想成超出的元素都會被設置成 null 就可以。(PS: 要使用 ArrayList 其型態一定是參考型態,如果使用基本型態會出現編譯失敗 ,而物件陣列的預設值為 null)。

    另外一個 toArray法是回傳 Object 陣列,由於兩個陣列基底型別不同時,不能互相參照,所以你無法直接將回傳的 Object 陣列轉成你要的型態陣列。但是你可以針對每個 Object 元素做轉型。

範例程式如下:

     static void toArrayDemo() {
        
        ArrayList<integer> list = new ArrayList<integer>(){{
            add(1);
            add(2);
            add(3);
            add(4);
        }};

        //"main" java.lang.NullPointerException
        //Integer[] test = null; 
        //test = list.toArray(test); 
        // or Integer[] test = list.toArray(null);
        
        // 配置的元素小於 ArrayList 所存的元素各數少時,
        // toArray 會幫你重新配置足夠的陣列個數來儲存。
        Integer[] test = list.toArray(new Integer[0]);
        System.out.print("<1>[ ");
        for (Integer val : test) {
            System.out.print(val + " ");
        }
        System.out.println("]");
        // 配置大於 ArrayList 所存的 元素個數,多餘的陣列元素都是 null
        Integer[] test2 = list.toArray(new Integer[10]);
        System.out.print("<2>[ ");
        for (Integer val : test2) {
            System.out.print(val + " ");
        }
        
        System.out.println("]");
        
        // 配置符合目前 ArrayList 所含的元素個數
        Integer[] test3 = list.toArray(new Integer[list.size()]);
        System.out.print("<3>[ ");
        for (Integer val : test3) {
            System.out.print(val + " ");
        }
        System.out.println("]");
        
        //無法將 Object 陣列轉成其他型態的陣列
        //[Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
        //Integer[] test4 = (Integer[] )list.toArray();
        
        Object [] obj = list.toArray();
        
        System.out.print("<4>[ ");
        for (Object val : obj) {
            // 你可以對每一個 Object 中的元素轉型成 Integer 型態的物件
            // 因為我們宣告的 ArrayList 是儲存 Integer 物件,所以每一個
            // Object 物件都是參考到  Integer 物件
            
            System.out.print( ((Integer)val).intValue() + " ");
            // 下面方式與上面轉型所列印出來的結果相同,因為每一個 Object 元素
            // 都是參考到 Integer 物件,而 Integer 的 toString method 就是列印其值。
            //System.out.print( val + " ");
        }
        System.out.println("]");
    }

輸出結果:
<1>[ 1 2 3 4 ]
<2>[ 1 2 3 4 null null null null null null ]
<3>[ 1 2 3 4 ]
<4>[ 1 2 3 4 ]

補充:
    Object[] obj = new Object[size] 與 Object[] intObj = new Integer[2]  的不同是,obj 陣列可以指定
任何型態的物件參考,每一個元素值不一定要儲存相同的物件。而 intObj 是參考到 Integer 陣列所以其元素只能儲存 Integer 物件,儲存其他型態物件會引發 "java.lang.ArrayStoreException" 例外事件。另外 intObj 是參考到 Integer 陣列,所以你可以將 intObj 指定給其他 Integer 陣列來參考。

範例程式如下:

    static void arrayDemo() {
        Object [] intobj = new Integer[2];
        System.out.println("obj instance Integer[] = " + (intobj instanceof Integer[]));
        obj[0] = new Integer(10);
        //Exception in thread "main" java.lang.ArrayStoreException: java.lang.Float
        //obj[1] = new Float(10.f);
        
        Object [] obj2 = new Object[2];
        System.out.println("obj2 instance Integer[] = " + (obj2 instanceof Integer[]));
        obj2[0] = new Integer(10);
        obj2[1] = new Float(10.f);
        System.out.println("obj2[0] = " + obj2[0] + " , obj2[1] = " + obj2[1]);
    }

2013年10月31日 星期四

ArrayList 移除 element 的問題

    今天查了 ArrayList 用法的時候,發現在 Javaworld 有人發了一篇 arraylist的移除問題,下面是他的 Sample Code
 
   ArrayList<integer> list = new ArrayList<integer>();
   list.add(2);
   list.add(2);
   list.add(3);
   list.add(1);
   list.add(2);
   System.out.println(list);

   for (int i=0; i<list.size(); i++){
      if(list.get(i)<3) {
         list.remove(i);
      }
   }
   System.out.println(list);

     原發問者想要將小於 3 的值全部移掉只剩下 3 這個元素,但是卻印出 [1 , 2],上面的的Sample Code 我有修改過,所以顯示為 [2,3,2] ,因為原程式在判斷條件小於3 的 if 後面多了分號 Orz。
     Anyway, 回到原來的問題,當你刪除一個元素時 size 也會跟著縮小,但是 i 的值卻會遞增,在 for 迴圈最後面加入除錯訊息,就可以知道為何印出 [2, 3, 2]。下面是我在 for 迴圈中加入除錯訊息所印出的資料:
i = 0 : [2, 3, 1, 2] size:4
i = 1 : [2, 3, 1, 2] size:4
i = 2 : [2, 3, 2] size:3

    要解決這個問題有下面三種方式

  1. 透過 Iterator 
  2. 透過 for 迴圈反向檢查,可以在 ConcurrentModificationException for ArrayList 中查到方式。
  3. 透過 CopyOnWriteArrayList

透過 Iterator 方式如下:
        
        Iterator<Integer> Allelement = list.iterator();
        while (Allelement.hasNext()) {
            if (Allelement.next() < 3) {
                Allelement.remove(); // 刪除最後 Iterator 所回傳的值,也就是目前所指到值
            }
        }
透過 for 迴圈反向檢查:
        
       for (int i = list.size() - 1; i >= 0; i--) {
            if(list.get(i) < 3){
                list.remove(i);
            }
        }

透過 CopyOnWriteArrayList:
        CopyOnWriteArrayList <Integer> list = 
                     new CopyOnWriteArrayList <Integer>();
        list.add(2);
        list.add(2);
        list.add(3);
        list.add(1);
        list.add(2);
        for (Integer val : list) {
            if (val  < 3) {
                list.remove(val);
            }
        }
請注意,使用 foreach 去詢訪 ArrayList 時,你不可以在 foreach 中 執行 remove,如果執行了應該會出現 java.util.ConcurrentModificationException 的例外訊息。


2013年10月23日 星期三

Scanner(System.in) 無法取的輸入的問題

    當你的只使用一個 Scanner(System.in) 在你的程式中並沒有甚麼問題,但是如果你有兩個類別都使用 Scanner(System.in) 來取得輸入時,最後使用 Scanner(System.in) 來取得輸入的類別是無法取得輸入,除非第一個使用的那個類別沒有呼叫close來關閉 Scanner。

    範例程式如下:
// InputDemo.java
import java.io.IOException;
import java.util.Scanner;

public class InputDemo {
    public static void main(String[] args) throws IOException {
        OtherInput otherInput = new OtherInput();

        int number = -1;
        Scanner scanner = new Scanner(System.in);
        
        // 嘗試執行下列敘述會得到IO例外訊息
        //System.out.println("System.in.available()" + System.in.available());
        
        System.out.print("Input a number:");
        if (scanner.hasNextInt()) {
            number = scanner.nextInt();
        }
        scanner.close();
        // 因為 scanner.nextInt() 沒有執行,所以 number 為 -1
        System.out.println("You input a number " + number);
    }
}

// OtherInput.java 
import java.util.Scanner;
public class OtherInput {
    public OtherInput() {
        Scanner scanner = new Scanner(System.in);
        
        int age = 0;
        String name = null;
        
        System.out.print("Please input your name:");
        if (scanner.hasNextLine()) {
            name = scanner.nextLine();
        }
        
        System.out.print("Please input your age:");
        if (scanner.hasNextInt()) {
            age = scanner.nextInt();
        }
        scanner.close();
        System.out.println("Your name: " + name + " and age: " + age);
    }
}

    在 Eclipse 下如果你沒有關閉 Scanner 會有一個警告訊息:"Resource leak: 'scanner' is never closed"。所以不建議不關閉 Scanner 物件。為什麼關閉 Scanner 物件會有問題呢? 因為當你執行 scanner.close() 時也會把 System.in 標準輸入也關閉掉,所以最後使用Scanner 物件的 calss 無法正常的取得輸入。
   你可以試著把上面的範例 InputDemo.java 中的 System.in.available() 註解符號拿掉,你會得到下列的例外訊息:
   Exception in thread "main" java.io.IOException: Stream closed
 at java.io.BufferedInputStream.getInIfOpen(Unknown Source)
 at java.io.BufferedInputStream.available(Unknown Source)
 at InputDemo.main(InputDemo.java:10)

   所以當你有多個類別要使用 Scanner(System.in) 取得輸入時,最好可以在主類別建立一個 Scanner 物件,然後將該物件傳遞給需要的類別,然後在主類別呼叫 Scanner 的 close 方法。

[其他參考]
java.util.NoSuchElementException - Scanner reading user input

Eclipse Console 視窗取得輸入的問題

     剛剛在嘗試了一下,發現是輸入法的問題,如果發現無法輸入可以將輸入切換到一般英文的模式,不要切換到有任何中文的輸入法。 : )

     在 Java 中要取得 Console 視窗輸入的文字可以透過 Scanner 物件來達到,今天如果你使用Eclipse 來開發時,當你的程式在取得輸入文字前,如果有先列印出一段提示文字時,你會發現 Eclipse 的 Console 視窗的游標會在最前面 (請參考下圖),並不會接在你所列印的提示文字後面,此時,如果你直接輸入任何文字嘗試取得輸入,會發現 Eclipse Console 視窗並不會顯示任何文字,且即便你按 Enter 想要結束輸入,Eclipse Console 視窗也不會有任何反應,此時你只能按停止執行或者重新執行程式來逃離這個狀況。

     要解決無法取得輸入的情況,當你執行程式時,必須先將游標移到正確的位置,然後再輸入,此時 Eclipse Console 視窗就可以正確的取得輸入的文字,注意,如果你的提示文字使用 println 來顯示,你必須移到下一行的開頭,如果使用 print 來顯示,則必須將游標移到提示文字的最後面才可開始輸入文字。

     範例程式如下:
import java.util.Scanner;

public class InputDemo {
    public static void main(String[] args) {
        int number = -1;
        Scanner scanner = new Scanner(System.in);
        System.out.print("Input a number:");
        
        if (scanner.hasNextInt()) {
            number = scanner.nextInt();
        }
        scanner.close();
        System.out.println("You input a number " + number);
    }
}


2013年9月25日 星期三

Java 查詢可用時區參數與設定時區

    Java 中可以透過 TimeZone 物件來查詢、設定 有關時區資訊。

查詢目前使用的時區:
TimeZone.getDefault().getID(); // Asia/Taipei
TimeZone.getDefault().getDisplayName(); // friendly name ex: 台灣標準時間

設定時區:
TimeZone tx = TimeZone.getTimeZone("Indian/Cocos"); // "Indian/Cocos" 就是 TimeZone ID
TimeZone.setDefault(tx);

列出可用時區:
String [] ids = TimeZone.getAvailableIDs();
for (String timezone : ids) {
    System.out.println(timezone + " " + 
          TimeZone.getTimeZone(timezone).getDisplayName());
}

   如果要取得目前日期時間可以透過 Calendar 物件取的相關訊息:
Calendar now = Calendar.getInstance();
int hour = now.get(Calendar.HOUR_OF_DAY);
int minute = now.get(Calendar.MINUTE);
int second = now.get(Calendar.SECOND);
int month = now.get(Calendar.MONTH);
int day = now.get(Calendar.DAY_OF_MONTH);
int year = now.get(Calendar.YEAR);
System.out.printf("現在是 %d/%d/%d %02d:%02d:%02d", 
    year, (month+1), day, hour, minute, second);

    要注意的是,Calendar 物件類別中的 MONTH 是用 0 到 11 來到表 1 月到 12 月,所以取得的數值要加 1 才會顯示正確。
 
    當你發現上面顯示的日期時間與你的電腦不符時,有可能是 Java 解譯器用錯時區設定;當 Java 解譯器不曉得目前的預設時區的話,會直接使用格林威治時間。

[相關資料]
[Java] 日期方法 (Date method)

2013年9月6日 星期五

Java Boolean getBoolean 總是回傳 false?

      之前試了 getBoolean 方法想要將字串轉成 boolean 型態,但是傳了 "true"、"True"、"TRUE" 最後的結果總是 false,用了google 查了一下,原來要使用 getBoolean 你必須設定 System 的 properties。 其實在 Java Doc 已經有提及到了,敘述如下:

      Returns true if and only if the system property named by the argument exists and is equal to the string "true".

      If there is no property with the specified name, or if the specified name is empty or null, then false is returned.


首先你可以透過 System.getProperties() 來取的目前執行你程式的一些系統參數設定,它主要是以 <key>=<value> 的形式顯示出來,所以當你要查詢某一個屬性值時,你可以透過 System.getProperty("key") 的方式得到 其對應的 value 值,如果該 key 不存在則回傳 null。

      另外除了透過 getBoolean 可以轉換成 基本型態的 boolean 值外,我們還可以透過 Boolean.valueOf(String s) 的方式轉換成 boolean的 Wrapper class型態。但 Boolean.valueOf(String s) 方法回傳 true 只有當字串為 "true"(大小寫無關) 時,其餘都回傳 false。

      我們可以透過 setProperty 來設定額外的系統參數,其設定型態也是 key/value的方式 ,setProperty ("key", "value"),除了設定 System.setProperty("TRUE", "TRUE"); 來讓 Boloean.getBoolean("TRUE") 來回傳 true ,我們也可以設定讓 Boloean.getBoolean("YES")也可以回傳 true 的值。

範例程式:

public class BooleanDemo {
    public static void main(String[] args) {
        System.out.println(System.getProperties());
        System.out.println("======================================");
        System.out.println(System.getProperty("java.runtime.name"));
        System.out.println("System.getProperty(\"true\") = " + System.getProperty("true"));
        System.out.println("System.getProperty(\"TRUE\") = " + System.getProperty("TRUE"));
        System.out.println("System.getProperty(\"True\") = " + System.getProperty("True"));
        
        System.out.println("Boolean.getBoolean(\"true\") = " + Boolean.getBoolean("true"));
        System.out.println("Boolean.getBoolean(\"TRUE\") = " + Boolean.getBoolean("TRUE"));
        
        System.out.println("Boolean.valueOf(\"true\") = " + Boolean.valueOf("true"));
        System.out.println("Boolean.valueOf(\"TRUE\") = " + Boolean.valueOf("TRUE"));
        
        System.setProperty("TRUE", "TRUE");
        System.setProperty("YES", "True");
        System.out.println("Boolean.getBoolean(\"TRUE\") = " + Boolean.getBoolean("TRUE"));
        System.out.println("Boolean.getBoolean(\"YES\") = " + Boolean.getBoolean("YES"));
        System.out.println("Boolean.getBoolean(\"yes\") = " + Boolean.getBoolean("yes"));

        System.clearProperty("YES");
        System.out.println("Boolean.getBoolean(\"YES\") = " + Boolean.getBoolean("YES"));
    }
}
    輸出結果: {java.runtime.name=Java(TM) SE Runtime Environment, sun.boot.library.path=C:\Program Files\Java\jre7\bin, java.vm.version=23.25-b01, java.vm.vendor=Oracle Corporation, java.vendor.url=http://java.oracle.com/, path.separator=;, java.vm.name=Java HotSpot(TM) Client VM, file.encoding.pkg=sun.io, user.country=TW, user.script=, sun.java.launcher=SUN_STANDARD, sun.os.patch.level=Service Pack 3, java.vm.specification.name=Java Virtual Machine Specification, user.dir=C:\Documents and Settings\Josh\JavaCode\BooleanDemo, java.runtime.version=1.7.0_25-b17, java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment, java.endorsed.dirs=C:\Program Files\Java\jre7\lib\endorsed, os.arch=x86, java.io.tmpdir=R:\TEMP\, line.separator= , java.vm.specification.vendor=Oracle Corporation, user.variant=, os.name=Windows XP, sun.jnu.encoding=MS950, java.library.path=C:\Program Files\Java\jre7\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:/Program Files/Java/jre7/bin/client;C:/Program Files/Java/jre7/bin;C:/Program Files/Java/jre7/lib/i386;C:\Ruby200\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program Files\Microsoft SQL Server\90\Tools\binn\;C:\Program Files\Perforce;C:\Program Files\Java\jdk1.7.0_07\bin;C:\Program Files\Android\android-sdk\tools;C:\Program Files\Android\android-sdk\platform-tools;C:\Program Files\apache-ant-1.9.1\bin;C:\Program Files\Perforce\Server;C:\Program Files\eclipse-SDK-4.2-win32;;., java.specification.name=Java Platform API Specification, java.class.version=51.0, sun.management.compiler=HotSpot Client Compiler, os.version=5.1, user.home=C:\Documents and Settings\Josh, user.timezone=, java.awt.printerjob=sun.awt.windows.WPrinterJob, file.encoding=UTF-8, java.specification.version=1.7, java.class.path=C:\Documents and Settings\Josh\JavaCode\BooleanDemo\bin, user.name=Josh, java.vm.specification.version=1.7, sun.java.command=BooleanDemo, java.home=C:\Program Files\Java\jre7, sun.arch.data.model=32, user.language=zh, java.specification.vendor=Oracle Corporation, awt.toolkit=sun.awt.windows.WToolkit, java.vm.info=mixed mode, sharing, java.version=1.7.0_25, java.ext.dirs=C:\Program Files\Java\jre7\lib\ext;C:\WINDOWS\Sun\Java\lib\ext, sun.boot.class.path=C:\Program Files\Java\jre7\lib\resources.jar;C:\Program Files\Java\jre7\lib\rt.jar;C:\Program Files\Java\jre7\lib\sunrsasign.jar;C:\Program Files\Java\jre7\lib\jsse.jar;C:\Program Files\Java\jre7\lib\jce.jar;C:\Program Files\Java\jre7\lib\charsets.jar;C:\Program Files\Java\jre7\lib\jfr.jar;C:\Program Files\Java\jre7\classes, java.vendor=Oracle Corporation, file.separator=\, java.vendor.url.bug=http://bugreport.sun.com/bugreport/, sun.io.unicode.encoding=UnicodeLittle, sun.cpu.endian=little, sun.desktop=windows, sun.cpu.isalist=pentium_pro+mmx pentium_pro pentium+mmx pentium i486 i386 i86} ====================================== Java(TM) SE Runtime Environment
System.getProperty("true") = null
System.getProperty("TRUE") = null
System.getProperty("True") = null

Boolean.getBoolean("true") = false
 Boolean.getBoolean("TRUE") = false 

Boolean.valueOf("true") = true
Boolean.valueOf("TRUE") = true

Boolean.getBoolean("TRUE") = true
Boolean.getBoolean("YES") = true
Boolean.getBoolean("yes") = false

Boolean.getBoolean("YES") = false


另外我在 Boolean.parseBoolean(“1”) = false…? 此篇討論文章,看到有人提供自己自製的方法來設定那些字串要回傳 true。 程式碼如下:

private boolean convertToBoolean(String value) {
    if ("1".equalsIgnoreCase(value)   || 
        "yes".equalsIgnoreCase(value) || 
        "true".equalsIgnoreCase(value)|| 
        "on".equalsIgnoreCase(value))
        return true;
    return false;
}

參考資料:
getBoolean(String str) and valueOf(String str) of Boolean class gives different output
有關 Boolean 的方法使用?
Boolean.parseBoolean(“1”) = false…?