2017年4月4日 星期二

[java] 條件控制

前言:

在 java 的條件控制中可分為 if-else 架構、三元運算子、switch-case 架構這三類,其中 if-else、三元運算子為條件型的判斷,條件必須為 true/false布林值;switch-case 為比對變數型的判斷,條件值比較多可以是 char、byte、short、int、enum、String(JDK7之後)值。有了這些條件控制語法,就可以依照條件的狀態來對程式碼進行控制,以下我會用範例來說明。


條件控制
判斷條件值的型態
if-else 架構
條件型(true / false)
三元運算子
條件型(true / false)
switch-case 架構
比對變數型(char、byte、short、int、enum、String)


1.條件型控制


if 敘述
指某一條件成立,執行某一件事情的概念,其中當條件成立會需要判斷 boolean 值,為true執行,若為false則不執行該區塊程式碼。
int score = 95;
if(score >= 60){
        System.out.println("成績 = " + score);
 }


if/else 敘述
if 語法可以加入 else 表示當 if 不成立的時候要做的事。例如:「如果考試不及格就要補考。」
int score = new Random().nextInt(100);
if(score >= 60){
        System.out.println("成績 = " + score);
        System.out.println("All pass");
} else if(score < 60){
        System.out.println("成績不及格 = " + score);
        System.out.println("需要補考!");
}


多重 if 敘述
有的時候需要判斷"可能狀況"會有好幾種,這個時候可以使用多重IF敘述來描寫。例如:「如果考試成績90分以上為A,80分以上為B,70分以上為C,60分以上為D,60分以下為E等,依分數的多寡作區分。」
int score = new Random().nextInt(100);
if(score >= 90){ System.out.println("成績 A"); } else if(score>=80 && score < 90){ System.out.println("成績 B"); } else if(score>=70 && score < 80){ System.out.println("成績 C"); } else if(score>=60 && score < 70){ System.out.println("成績 D"); } else if(score < 60){ System.out.println("成績 E"); } }

巢狀 if/esle 敘述
if/else 敘述中又包含其它 if 敘述,有的時候需要先做初步判斷好的條件下,再細部判斷處理,這時候就可以使用巢狀敘述。
int score = new Random().nextInt(100);
        if(score >= 60){
            System.out.println("score = " + score);
            System.out.println("All pass");
        } else if(score < 60){
            System.out.println("score = " + score);
            if(score < 60 && score >= 40){
                System.out.println("成績介於60-40分,需要補考!");
            }else if(score < 40 ){
                System.out.println("成績低於40分,需要重修!");
            }
        }


三元運算子
(條件式 ? true : false) 可以說是 if/else 的簡化敘述,也是屬於條件行控制的一種。這邊以巢狀if/else範例做修改,程式如下:
int score = new Random().nextInt(100);
System.out.println("score = " + score);
        if(score >= 60){
            System.out.println("All pass");
        } else if(score < 60){
            System.out.println((score < 60 && score >= 40) ? "成績介於60-40分,需要補考!" : "成績低於40分,需要重修!");
        }


2.比對變數型控制

switch case
跟條件型控制差一樣,也有多選一的的概念,只不多改成以比對變數控制。首先看看switch的括號,當中置放要取得值的變數或運算式,值必須是整數、字元、字串或Enum,取得值後會開始與case中設定的整數、字元、字串或Enum比對,如果符合就執行之後的陳述句,直到遇到break離開switch區塊,如果沒有符合的整數、字元、字串或Enum,則會執行default後的陳述句,default不一定需要,如果沒有預設要處理的動作,也可以省略default。
int score = new Random().nextInt(100);
        int level = score / 10;
        System.out.println("成績 = " + score);
        switch (level) {
            case 10:
            case 9:
                System.out.println("成績 A");
                break;
            case 8:
                System.out.println("成績 B");
                break;
            case 7:
                System.out.println("成績 C");
                break;
            case 6:
                System.out.println("成績 D");
                break;
            default:
                System.out.println("成績不及格,需要補考!");
        }

改寫成switch case程式碼會比 if/else 更容易閱讀,另一方面範例中的level只需要讀取一次,在效能上也會比較好。

2017年3月26日 星期日

[Java] equals 與 == 的差異

前言:

通常我們從後台取得 json 資料後都會轉成 String ,並解析其參數值拿來使用,而在使用前最好先判斷參數值是否存在或相同再做解析,這樣可以避免不可預期的錯誤(有可能資料本身就沒有帶到參數或參數打錯字等...)。而這時候大多數人都會想到用 == 或 Sting.equals()來做判斷,不過他們還是有些差異唷,以下我會用一些範例來說明 == 或 Sting.equals() 的差異。
ps:可以的話(String pool)的觀念也要知道一下會比較好,良葛哥學習筆記字串特性中有提到也寫得很不錯可以參考看看)。


1.==
== 其實是在判斷 stack 內的值,當兩個參考資料型別變數指向同一物件, == 運算子的結果會為 true; 且若兩個參考資料型別變數指向不同物件時,結果為 false。


2.equals
String 類別有提供 equals 這個方法如下方程式碼,先比較兩物件是否為相同類型的類別後在比較其內容值是否相同,是就回傳 true,否則回傳 false。

String.java
public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }



程式範例如下:
package pkg;

public class Main {

    public static void main(String[] args) {
        String s4 = new String("restful");
        String s5 = new String("restful");
        String s6 = new String("peaceful");
        String s7 = s4;
        String s8 = "restful";
        String s9 = "restful";
        
        System.out.println(s4.equals(s5)); //s4和s5所帶的值相同---true
        System.out.println(s4.equals(s6)); //s4和s6所帶的值不相同----false
        System.out.println(s4 == s5); //s4和s5各new了不同的記憶體空間----false
        System.out.println(s4 == s7); //因為把s7指向了和s4所指向的同一個空間----true
        System.out.println(s4 == s8); //因為s4 new了一個新空間,而s8則在字串池中---false
        System.out.println(s8 == s9); 
        //s8和s9都在字串池中,為了節省記憶體空間,在字串池中,只要值相同,都會指向同一個記憶體空間-----true
    }

}



2017年3月22日 星期三

[Java] 邏輯運算子 &、| 、&&、|| 間運算上的差異

前言:

之前工作上在使用邏輯運算子判斷時,程式亂跑跑到跟我想的完全不一樣,後來開 debug 看才知道,原來是我自己的觀念不夠清楚。哈~因為自己的觀念不清楚導致 bug 產生,其實程式碼是不會錯的,會錯的是通常自己的思考邏輯寫錯。因此才會想說稍微複習一下,寫出這篇來提醒自己...


邏輯運算子
邏輯運算子
說明
範例
特性
AND
x & y
AND的特性只要1個運算元為 False,整個式子就為 False
運算時應該要同時拿2個運算元的資料來作運算。
OR
x | y
OR的特性只要1個運算元為True,整個式子就為 True
運算時應該要同時拿2個運算元的資料來作運算。
NOT
! a
如果條件為 True,則得到為 False。
&&
(短路型)
AND
x && y
AND的特性只要1個運算元為False,整個式子就為 False
假如第一個運算元的資料已經為False,就不會再判別第二個運算元資料,直接輸出False。
||
(短路型)
OR
x || y
OR的特性只要1個運算元為True,整個式子就為 True
假如第一個運算元的資料已經為True,就不會再判別第二個運算元資料,直接輸出 True。

程式碼(一):
package pkg;

public class Test {

    public static void main(String[] args) {
        try {
            int x = 0;
            int y = 3;
            if ((x != 0) & (y / x < 5)) {
                System.out.println("False - 跳離!");
            } else {
                System.out.println("x = " + x + " ; y = " + y);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

首先看到程式碼第九行使用的邏輯運算子,因為 &(AND) 運算符號會同時運算左右的2個運算元,所以當第十行執行到(y / x < 5)有錯誤時,會直接跳出,並在 catch 中印出錯誤訊息!


程式碼(一)執行會遇到除以0的錯誤!如下:

若將程式碼(一)的&改為&&,程式碼(二)如下:
package pkg;

public class Test {

    public static void main(String[] args) {
        try {
            int x = 0;
            int y = 3;
            if ((x != 0) && (y / x < 5)) {
                System.out.println("False - 跳離!");
            } else {
                System.out.println("x = " + x + " ; y = " + y);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

程式碼(二)這時並不會遇到除以0的錯誤,因為 && (Short-circuit AND) 在判別完第一個運算元
為False的時候,它就已經直接輸出False了!

程式碼(二),則得到的結果為:

2017年3月21日 星期二

[Java] 資料型態介紹 與 記憶體配置

前言:
在開始討論 Java 資料型別前大家是否有想過為什麼要有資料型別這個東西呢?
所以一開始想先給大家有『要計算前必先記憶』這個觀念,舉個例子來說:
想像自己是加油站員工,假設汽油每公升 i 元,幫一台機車加 j 公升的汽油,那總共要跟客人收 i x j 元.我們是不是會先將要計算的數字 i 與 j 記在大腦內,然後再開始計算,由此可知『要計算前必先記憶』。



相同的概念,電腦會把要計算的值先存入記憶體內,因為 i 與 j 的值是變動的,所以我們在撰寫程式時必須透過資料型別來告訴電腦所需的記憶體空間。而要記在哪邊?用什麼形式記?以及紀錄的數值要怎麼變動?這些都會跟資料型別有關,以下我們來說明。



開始正題:
Java 的資料型別主要可分為 基本資料型別參考資料型別 兩種,如下大致區分,其基本資料型別相關資料也在下圖提供。
1.基本資料型態 Primitive Type
   在Java預設八種基本的資料型態:
整數 → byte、short、int 與 long
浮點數 → float 與 double
字元 → char
      布林值 → boolean
2.參考資料型態 Reference Type
   上述8種資料型別以外都屬與參考資料型別 :
   字串(String)
自定義的類別 (class)
陣列 (Array)
介面 (interface)
列舉 (enum)
       ...


接著為了更瞭解這兩種資料型別在實際儲存與用法上的差異,我們在說明記憶體中的儲存空間配置。
  • Global
存放著宣告為 static 的類別成員變數,在 Java 程式執行期間資料會一直被維護著。成員 (屬性、方法) 宣告時若使用關鍵字 static 修飾,該成員變成屬於類別 (class) 而非物件 (object) ,因此使用 static 就不需要先建立物件。
  • Stack
存放著宣告為基本資料型別的變數內容物件變數的參考內容值的地方,當有新宣告產生時, stack 利用指標直接指向該變數,以幫助程式能快速存取該變數的內容值。
  • Heap
存放著宣告為參考資料型別,當宣告一個參考資料型別物件並用 new 關鍵字產生物件實體,物件參考值將會存在記憶體的 stack 中, 新建立的物件實體則在記憶體的 heap 中配置一塊新區域存放,同時在 stack 中的物件參考值也將會指向 heap 中的物件實體。

[java] 條件控制

前言: 在 java 的條件控制中可分為 if-else 架構、三元運算子、switch-case 架構這三類,其中 if-else、三元運算子為條件型的判斷,條件必須為 true/false布林值;switch-case 為比對變數型的判斷,條件值比較多可以是 char、...