Java無限迴圈問題
首先需要說明的是,以下問題都是出自《Java解惑》,這裡做一個整理,也加深一下印象。
下面所有的問題都是給出一個迴圈,給它加一個什麼樣的變數宣告,使它作用於迴圈上時能夠使迴圈無限迴圈下去(即變成一個無限迴圈)。
1.
for (int i = start; i <= start + 1; i++) {}
這個問題還比較簡單,只需要這樣宣告即可(注意:上面的是小於等於號):int start = Integer.MAX_VALUE - 1;
2.
While (i == i + 1) {}
如果 i 在迴圈開始之前被初始化為無窮大,無窮大加 1 還是無窮大,那麼終止條件測試(i == i + 1)就會被計算為 true,從而使迴圈永遠都不會終止。這樣宣告即可:double i = Double.POSITIVE_INFINITY;
事實上,任何足夠大的浮點數都可以實現這一目的,例如: double i = 1.0e40; 這樣做之所以可以起作用,是因為一個浮點數值越大,它和其後繼數值之間的間隔就越大。浮點數的這種分佈是用固定數量的有效位來表示它們的必然結果。對一個足夠大的浮點數加 1 不會改變它的值,因為 1 是不足以“填補它與其後繼者之間的空隙”。
3.
while (i != i) { }
IEEE 754 浮點算術保留了一個特殊的值用來表示一個不是數字的數量,這個值就是 NaN(“不是一個數字(Not a Number)”的縮寫),對於所有沒有良好的數字定義的浮點計算,例如 0.0/0.0,其值都是它。規範中描述道,NaN 不等於任何浮點數值,包括它自身在內。因此,如果 i 在迴圈開始之前被初始化為 NaN,那麼終止條件測試(i != i)的計算結果就是 true,迴圈就永遠不會終止。很奇怪但卻是事實。 可以這樣宣告:double i = 0.0 / 0.0;
為了表達清晰,可以使用標準類庫提供的常量: double i = Double.NaN;
4.
while (i != i + 0) { }
注意:此題不使用浮點數。
我們必然可以得出這樣的結論,即 i 的型別必須是非數值型別的,並且這其中存在著解謎方案。唯一的 + 操作符有定義的非數值型別就是 String。+ 操作符被過載了:對於 String 型別,它執行的不是加法而是字串連線。如果在連線中
的某個運算元具有非 String 的型別,那麼這個操作書就會在連線之前轉換成字串。
事實上,i 可以被初始化為任何值,只要它是 String 型別的即可,例如:String i = "Hello";
5.
while (i <= j && j <= i && i != j) { }
在Java5.0版本及以後,<=操作符在原始數字型別集上是反對稱的,但是<=操作符在被包裝的數字型別(Byte、Character、Short、Integer、Long、Float 和 Double)的運算元上不是反對稱的,因為 Java 的判等操作符(==和!=)在作用於物件引用時,執行的是引用ID 的比較,而不是值的比較。
所以這樣宣告即可: Integer i = new Integer(0); Integer j = new Integer(0);
public class Test4
{
public static void main(String[] args)
{
System.out.println(new Integer(0) == 0); //輸出:true
System.out.println(new Integer(0) == new Integer(0)); //輸出:false
}
}
6.
while (i != 0 && i == -i) { }
可以推斷出 i 的型別必然是整數型的。總共存在偶數個 int 數值——準確地說有2的32次方個——其中一個用來表示 0,這樣就剩些奇數個 int 數值來表示正整數和負整數,這意味著正的和負的 int 數值的數量必然不相等。這暗示著至少有一個 int數值,其負值不能正確地表示成為一個 int 數值。
事實上,恰恰就有一個這樣的 int 數值,它就是 Integer.MIN_VALUE,十六進位制表示是 0x80000000。其符號位為 1,其餘所有的位都是 0。如果我們對這個值取負值,那麼我們將得到 0x7fffffff+1,也就是 0x80000000,即
Integer.MIN_VALUE!因此,Integer.MIN_VALUE 是它自己的負值,Long.MIN_VALUE 也是一樣。對這兩個值取負值將會產生溢位,但是 Java 在整數計算中忽略了溢位。
因此可以這樣宣告:int i = Integer.MIN_VALUE; 或者:long i = Long.MIN_VALUE;
public class Test4
{
public static void main(String[] args)
{
int i = Integer.MIN_VALUE;
long j = Long.MIN_VALUE;
System.out.println(i == -i); //輸出:true
System.out.println(j == -j); //輸出:true
}
}
相關文章
- 無限for迴圈(死迴圈)
- javascript無限迴圈滾動JavaScript
- 理解 vue-router的beforeEach無限迴圈的問題Vue
- iOS-無限迴圈輪播圖iOS
- IOS 無限迴圈小視訊播放iOS
- ViewPager實現左右無限迴圈滑動Viewpager
- 原生js系列之無限迴圈輪播元件JS元件
- android可以無限迴圈滑動的ViewPagerAndroidViewpager
- AlloyTouch之無限迴圈select外掛
- require()迴圈引用問題UI
- AirDrop無限迴圈攻擊,你的iPhone還好嗎?AIiPhone
- iOS無限迴圈輪播圖(只使用三個imageView)iOSView
- ThinkPHP 無限遞迴PHP遞迴
- 直播系統app原始碼,垂直,水平無限迴圈滑動APP原始碼
- iOS開發系列--無限迴圈的圖片瀏覽器iOS瀏覽器
- 無迴圈 JavaScriptJavaScript
- Java迴圈Java
- iview Tree資料格式問題,無限遞迴樹處理資料View遞迴
- win10無限迴圈自動修復怎麼辦_win10開機無限迴圈自帶修復失敗重啟如何解決Win10
- win10自動修復失敗無限迴圈怎麼辦_win10開機自動修復失敗無限迴圈如何解決Win10
- 陣列元素迴圈右移問題陣列
- 迴圈內臨時變數問題變數
- FastJson中迴圈引用的問題ASTJSON
- 迴圈(Java篇)Java
- 無限遞迴導致StackOverflowError遞迴Error
- sql無限遞迴查詢SQL遞迴
- 面試題:Spring 的迴圈依賴問題面試題Spring
- 關於一個迴圈請求與迴圈計時器的問題
- 1008 陣列元素迴圈右移問題 (20 分)java陣列Java
- 【基礎題】【for迴圈】二重迴圈
- 無縫迴圈滾動
- Linux while 迴圈中使用ssh問題LinuxWhile
- JavaScript 深複製的迴圈引用問題JavaScript
- 迴圈請求報204問題分析
- v-for 迴圈 index的傳值問題?Index
- JavaScript 中 for in 迴圈和陣列的問題JavaScript陣列
- c++類迴圈依賴的問題C++
- jacksonjava轉jsonhibernate造成的堆疊溢位無限遞迴問題JavaJSON遞迴