java謎題(1)

來源:互聯網
上載者:User
謎題1,奇數性
public static boolean isOdd(int i ){    return i%2==1;}

當 i 是一個負奇數時,i % 2 等於-1 而不是1, 因此 isOdd 方法將錯誤地返回 false。為了防止這種意外,請測試你的方法在為每一個數值型參數傳遞負數、零和正數數值時,其行為是否正確。 

這個問題很容易訂正。只需將 i % 2 與 0 而不是與1 比較,並且反轉比較的含義即可: 

public static boolean isOdd(int i){ 
return i % 2 != 0;
}

如果你正在在一個效能臨界(performance-critical)環境中使用isOdd 方法,那麼用位操作符AND(&)來替代取餘操作符會顯得更好: 

public static boolean isOdd(int i){ 
return (i & 1) != 0;

}
謎題2,找零時刻浮點數不夠精確,只可用int或者BigDecimal類型做金錢計算。(另外單獨說明)謎題3,長整數
public class LongDivision{ 
public static void main(String args[]){
final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY);

}

}

我們計劃列印1000,遺憾的是,它列印的是5。這裡到底發生了什麼呢? 
     問題在於常數MICROS_PER_DAY的計算“確實”溢出了。儘管計算的結果適合放入long中,並且其空間還有富餘,但是這個結果並不適合放入int中。這個計算完全是以int運算來執行的,並且只有在運算完成之後,其結果才被提升到long,而此時已經太遲了:計算已經溢出了,它返回的是一個小了200倍的數值。從int提升到long是一種拓寬原始類型轉換(widening primitive conversion),它保留了(不正確的)數值。這個值之後被MILLIS_PER_DAY整除,而MILLIS_PER_DAY的計算是正確的,因為它適合int運算。這樣整除的結果就得到了5。 

那麼為什麼計算會是以int 運算來執行的呢?因為所有乘在一起的因子都是int數值。當你將兩個int 數值相乘時,你將得到另一個int 數值。Java不具有目

標確定類型的特性,這是一種語言特性,其含義是指儲存結果的變數的類型會影響到計算所使用的類型。 

通過使用long常量來替代int常量作為每一個乘積的第一個因子,我們就可以很容易地訂正這個程式。這樣做可以強製表達式中所有的後續計算都用long運

作來完成。儘管這麼做只在MICROS_PER_DAY運算式中是必需的,但是在兩個乘積中都這麼做是一種很好的方式。相似地,使用long作為乘積的“第一個”數值也並不總是必需的,但是這麼做也是一種很好的形式。在兩個計算中都以lon數值開始可以很清楚地表明它們都不會溢出。下面的程式將列印出我們所期望的1000: 

public class LongDivision{ 
public static void main(String args[ ]){
final long MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000;
final long MILLIS_PER_DAY = 24L * 60 * 60 * 1000;
System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY);
}

}

這個教訓很簡單:當你在操作很大的數字時,千萬要提防溢出——它可是一個緘默殺手。即使用來儲存結果的變數已顯得足夠大,也並不意味著要產生結果的計算具有正確的類型。當你拿不準時,就使用long運算來執行整個計算。

謎題4,初級問題
public class Elementary{ 
public static void main(String[] args){
System.out.println(12345+5432l);
}
}

System.out.println(12345+5432L); 

注意1和L(l)的區別.謎題5,十六進位的趣事

public class JoyOfHex{ 
public static void main(String[] args){
System.out.println(
Long.toHexString(0x100000000L + 0xcafebabe));
}
}

十六進位最高位被置位了,為負數。謎題6,多重轉型
public class Multicast{ 
public static void main (String[] args){
System.out.println((int)(char)(byte) -1);
}
}

窄的整型轉換成較寬的整型時符號擴充規則:如果最初的數實值型別是有符號的,那麼就執行符號擴充(即如果符號位

為1,則擴充為1,如果為零,則擴充為0);如果它是char,那麼不管它將要被提升成什麼類型,都執行零擴充。

瞭解上面的規則後,我們再來看看迷題:因為byte是有符號的類型,所以在將byte數值-1(二進位為:11111111)提

升到char時,會發生符號位擴充,又符號位為1,所以就補8個1,最後為16個1;然後從char到int的提升時,由於是

char型提升到其他類型,所以採用零擴充而不是符號擴充,結果int數值就成了65535。

如果將一個char數值c轉型為一個寬度更寬的類型時,只是以零來擴充,但如果清晰表達以零擴充的意圖,則可以考慮

使用一個位元遮罩:

Java代碼

2 int i = c & 0xffff;//實質上等同於:int i = c ; 

如果將一個char數值c轉型為一個寬度更寬的整型,並且希望有符號擴充,那麼就先將char轉型為一個short,它與

char上個具有同樣的寬度,但是它是有符號的:

Java代碼

3 int i = (short)c; 

如果將一個byte數值b轉型為一個char,並且不希望有符號擴充,那麼必須使用一個位元遮罩來限制它:

Java代碼

4 char c = (char)(b & 0xff);// char c = (char) b;為有符號擴充 

System.out.println(12345+5432L); 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.