Promotion 與 Cast


如果你寫個程式片段:
double PI = 3.14;

這沒有問題,但如果你寫個程式片段:
float PI = 3.14;

你會得到一個possible loss of precision的編譯錯誤!如果你要通過編譯,你必須這麼寫:
float PI = (float) 3.14;

這就是所謂的CAST,編譯器在編譯時,就會雞婆地換成這個:
float PI = 3.14F;

在浮點數後寫F(或f),這表示告訴編譯器,這個浮點數要使用float的資料型態(長度)。如果你只寫下浮點數而沒有寫F(或f),例如第一個程式片段,則編譯器會換成這個:
double PI = 3.1400000000000001D;

也就是不指定F(或f)時,浮點數預設會使用double的型態。

再來看整數的部份。如果你寫下:
int number = 10;

這沒有問題。如果你寫下:
int number = 2147483648;

編譯時會得到integer number too large的錯誤。你以為int變數number裝不下2147483648,認為這樣可以解決問題:
long number = 2147483648;

其實不然,事實並非是number裝不下2147483648(如果是的話,應該是possible loss of precision才對)!而是當你在程式中寫下一個整數時,預設是使用不超過int型態的長度。2147483648超出了int型態的長度,你要直接告訴編譯器,用long來配置整數的長度,也就是:
long number = 2147483648L;

當你在程式中寫下一個整數時,預設是使用不超過int型態的長度:
byte number = 10;

這樣OK!但這樣不行:
byte number = 128;

這樣就會出現
possible loss of precision

再來看運算,如果運算式中包括不同型態的數值,則運算時以最長的長度為主,其它數值自動提昇,也就是所謂的Promotion。例如:
int a = 10;
double b = a * 3.14;

此時因為3.14是浮點數(而且是double),所以a提昇為double,事實上,編譯器會變成這樣:
int i = 10;
double d = (double)i * 3.1400000000000001D;

再來如果運算元都是不大於int的整數,則自動全部提昇為int型態再進行運算,所以,下面這個通不過編譯:
short a = 1;
short b = 2;
short c = a + b;

第三行會出現
possible loss of precision,你要改成這樣才對:
short a = 1;
short b = 2;
short c = (short) (a + b);

這個也通不過編譯,一樣第三行possible loss of precision
short a = 1;
long b = 2;
int c = a + b;

因為運算元中,b為long,所以a自動提昇為long,運算後為long,裝不進int的c中!這樣才可以:
short a = 1;
long b = 2;
int c = (int)(a + b);

最後有兩個問題。第一,誰可以指出,我1975-5-26出生,為何算出來是700多歲?
import java.util.*;
import java.text.*;

// 這個程式運算結果是錯的!錯在哪?
public class Main {
public static void main(String[] args) throws Exception {
DateFormat dateFormat =
new SimpleDateFormat("yyyy-MM-dd");
Date birth = dateFormat.parse(args[0]);
Date current = new Date();
long life = current.getTime() - birth.getTime();
System.out.println("你今年的歲數為:" +
(life / (365 * 24 * 60 * 60 * 1000)));
}
}

第二個問題,下面這個程式執行結果為何?
public class Main {
public static void main(String[] args) {
System.out.println(Integer.MIN_VALUE == -Integer.MIN_VALUE);
}
}