4-3 宣告、使用變數

在 Java 程式中寫下一個數值,則編譯器會為該數值配給一個記憶體空間,然而在程式設計時,您經常會需要先擁有記憶體空間,該空間中要放些什麼數值您事先並無法得知,必須要等程式開始執行並運算之後,才會將運算結果儲存至該空間中。

圖4-5、您需要一個空間,但還不知道要放些什麼!

您可以先宣告一個記憶體空間,告知編譯器這個空間將儲存的資料是什麼型態,並且這個記憶體空間會有個名稱,稍後您執行程式時,可以使用這個名稱,將指定資料存入預先宣告的記憶空間之中,這樣的名稱與空間叫作「變數」( Variable ),而宣告的這個動作稱之為變數宣告

圖4-6、變數宣告為您保留記憶體空間

• 變數的宣告與使用

在方法中進行變數宣告的語法如下:

type identifier = [value];
                            

其中 type 用來宣告變數的資料型態,可使用關鍵字 byte、short、int、long、float、double、boolean 等來宣告,主要看您需要多大的空間來儲存資料。

dentifier 是您要對變數取的名稱,變數的名稱必須能表示出該變數的作用,例如用 ageOfStudent 這樣的名稱來表示,這個變數中儲存的資料是學生的年齡。

=是指定運算子( Assignment operator ),用來將右邊的 value 指定給左邊的變數來儲存。

public class VariableDemo {
    public static void main(String[] args) {
        //宣告並指定值
        int ageOfStudent = 18;
        char sexOfStudent = 'M';

        // print()方法在顯示文字後不換行
        System.out.print("學生年齡: ");
        System.out.println(ageOfStudent);
        System.out.print("學生姓別: ");
        System.out.println(sexOfStudent);
        //取得變數的值

        ageOfStudent = 20;
        sexOfStudent = 'F';
        System.out.print("學生年齡: ");
        System.out.println(ageOfStudent);
        System.out.print("學生姓別: ");
        System.out.println(sexOfStudent);
    }
}
                            
程式碼 4-3 VariableDemo.java

注意在第 3 行中,宣告 char 變數在指定值時,字元值必須使用單引號包括,在宣告變數並指定值之後,您可以直接使用變數名稱來取得變數所儲存的值,如第 8 行與第 10 行所示範的,而如果您打算修改變數中所儲存的值,則再使用指定運算子來指定,如第 12 行與 13 行所示範的,不必再重新宣告變數,範例 4-3 的編譯與執行結果如下:

圖4-7、範例 4-3 的執行結果

在 Java 中,變數的名稱是有大小寫之分的,也就是說ageOfStudent 與 ageofstudent 這樣的名稱是兩個不同的變數。

您也可以指派一個變數的值給其它變數,右邊變數的值會複製一份給左邊變數,例如以下的程式片段中,age 變數的值會是 ageOfStudent 變數的值,所以程式會在螢幕上顯示 18:

int ageOfStudent = 18;
int age = ageOfStudent; // 指定變數給另一個變數
System.out.println(age);
                            

有時候您想要指定一個值給變數,之後不再改變它的內容,目的是為了方便使用名稱來取用某個數值,例如用 PI 這個變數名來取用 3.14159 的值,則您可以在宣告變數時,一併使用 final 關鍵字,例如:

final double PI = 3.14159;
                            

使用 final 關鍵字宣告的變數,在指定值之後就不能改變它的值,如果您試圖改變,則編譯器會告訴您不可以這麼作,舉個例子來說:

final double PI = 3.14159;
PI = 3.14; // 試圖改變 final 所宣告的變值之值
                            

如果程式中撰寫了以上的程式片段,則編譯時 就會出現 cannot assign a value to final variable 的錯誤訊息。

重點提示

使用 final 宣告的變數,通常變數名稱會以全部大寫來表示,這可以提醒程式設計人員所使用的變數可能是使用 final 宣告的變數。

宣告變數會使得編譯器提供一塊記憶體空間,供您未來儲存數值,空間被宣告之後,當中可能含有未知的數值,在未指定數值給變數之前,您不可以直接取用變數的值,事實上編譯器也會發生錯誤訊息,例如:

int ageOfStudent; // 宣示變數但不指定值
System.out.println(ageOfStudent); // 顯示變數
                            

上面的程式片段在編譯時將會出現 variable ageOfStudent might not have been initialized 錯誤訊息,您必須在指定值之後才能取用變數,例如:

int ageOfStudent = 18;
System.out.println(ageOfStudent);
                            

• 晉升(Promotion)與轉型(Casting)

在宣告變數時必須使用關鍵字 byte、short、int、long、float、double、boolean 等告知編譯器,您將儲存什麼資料型態的資料至變數中,而您在程式中寫下一個字面值時,編譯器會預設它的資料型態,如果在宣告變數並指定值時,這樣寫不會有什麼問題。

int age = 18;
double score = 90.5;
                            

因為編譯器會為數值 18 分配 int 型態的記憶體空間,為數值90.5 分配 double 型態的記憶體空間,但如果您這麼宣告的話,編譯器會出現錯誤訊息:

int age = 2036854775808;
float score = 90.5;
                            

因為 2036854775808 超過了 int 型態變數所能儲存的範圍,編譯器會出現 integer number too large 的錯誤訊息;90.5 編譯器預設為它提供了 double 型態的空間,而您卻指定這個值給 float 型態的變數,編譯器會出現 possible loss of precision 的錯誤訊息。

當提供的數值其資料型態與變數的資料型態不符時,我們必須考慮數值的晉升( Promotion )轉型( Casting )問題。

晉升( Promotion )

如果變數的資料型態其儲存範圍比指定的數值之資料型態為大時,則會發生數值型態晉升的動作,簡單的說,就是數值的型態會自動提昇為符合變數之資料型態,舉例來說,下面的程式碼會發生晉升的動作:

long money = 10;
                            

10 被指定給 money,由於變數 money 是 long 型態,資料型態自動從 int 變為 long,資料型態晉升動作發生時,編譯器不會有任何的訊息出現。

轉型( Casting )

如果數值的資料型態之儲存範圍比變數的資料型態為大時,由於原數值無法將所有的容量儲存至變數中,因而編譯器會提出錯誤訊息,例如:

long money = 10;
int smallMoney = money;
                            

在上面的程式片段中,money 儲存了 long 型態的數值(10被晉升為 long 型態),而您將 money 指定給 smallMoney 時,由於 smallMoney 變數的型態是 int,其容量不足以容納 long 型態數值,因而會出現以下的錯誤訊息:

possible loss of precision
found : long
required: int
        int smallMoney = money;
                            

如果您確定要將資料型態大的值指定給資料型態小的變轉型數,則您必須明確進行轉型(Casting)的動作,方法是使用括號()包括目標資料型態的關鍵字,例如以下的程式片段就不會有錯誤:

long money = 10;
int smallMoney = (int) money;
                            

同樣的方式也適用於 float 與 long 的轉型,例如以下的程式片段是沒有問題的:

double pi = 3.14159;
float piAlso = (float) 3.14; // 轉型為 float
                            

當然,轉型會縮小記憶體空間,原來資料有可能會失去某些訊息,例如失去數值上的一些精確度。

圖4-8、轉型會可能讓資料失去一些資訊