Java 中的 IllegalStateException 和 NoSuchElementException 有什麼區別?
當您在非法或不適當的時間呼叫方法時,會生成 IllegalStateException。
例如,ArrayList 類的 remove() 方法在呼叫 next() 或 previous() 方法後刪除最後一個元素。
- 刪除當前位置的元素後,您需要移動到下一個元素才能刪除它,即每次呼叫 next() 方法,只能呼叫一次 remove() 方法。
- 由於列表的初始位置(指標)將在第一個元素之前,因此在不呼叫 next 方法的情況下,您不能呼叫此方法。
如果您在其他情況下呼叫 remove() 方法,它將丟擲 java.lang.IllegalStateException。
示例:在移動到第一個元素之前刪除元素
import java.util.ArrayList; import java.util.ListIterator; public class NextElementExample{ public static void main(String args[]) { //Instantiating an ArrayList object ArrayList<String> list = new ArrayList<String>(); //populating the ArrayList list.add("apples"); list.add("mangoes"); //Getting the Iterator object of the ArrayList ListIterator<String> it = list.listIterator(); //Removing the element without moving to first position it.remove(); } }
執行時異常
Exception in thread "main" java.lang.IllegalStateException at java.util.ArrayList$Itr.remove(Unknown Source) at MyPackage.NextElementExample.main(NextElementExample.java:17)
示例:在呼叫一次 next() 方法後,再次呼叫 next() 方法兩次
import java.util.ArrayList; import java.util.ListIterator; public class NextElementExample{ public static void main(String args[]) { //Instantiating an ArrayList object ArrayList<String> list = new ArrayList<String>(); //populating the ArrayList list.add("apples"); list.add("mangoes"); //Getting the Iterator object of the ArrayList ListIterator<String> it = list.listIterator(); //Removing the element with out moving to first position it.next(); it.remove(); it.remove(); } }
輸出
Exception in thread "main" java.lang.IllegalStateException at java.util.ArrayList$Itr.remove(Unknown Source) at MyPackage.NextElementExample.main(NextElementExample.java:17)
在迴圈中嘗試呼叫此方法也屬於這種情況。
it.next(); while(it.hasNext()) { it.remove(); }
解決方案
在上述情況下,要解決 IllegalStateException,您需要正確地呼叫 remove() 方法(僅在呼叫 next() 後呼叫一次)。
示例
import java.util.ArrayList; import java.util.Arrays; import java.util.ListIterator; public class NextElementExample{ public static void main(String args[]) { //Instantiating an ArrayList object ArrayList<String> list = new ArrayList<String>(); //populating the ArrayList list.add("apples"); list.add("mangoes"); //Getting the Iterator object of the ArrayList ListIterator<String> it = list.listIterator(); //Removing the element with out moving to first position System.out.println(Arrays.toString(list.toArray())); while(it.hasNext()) { it.next(); it.remove(); } System.out.println(Arrays.toString(list.toArray())); } }
輸出
[apples, mangoes] []
類似地,在每種情況下,要處理 IllegalStateException,您需要在其合法位置呼叫導致異常的方法。
NoSuchElementException
在使用 Enumeration、Iterator 或 tokenizer(例如 next() 或 nextElement())的訪問器方法訪問集合、陣列或其他物件的內容時,如果您嘗試從空物件獲取元素,或者如果您嘗試在到達物件(集合、陣列或其他)的末尾後獲取下一個元素,則會生成 NoSuchElementException。
例如,
- 如果您在空列舉物件上呼叫 Enumeration 類的 nextElement() 方法,或者如果當前位置位於 Enumeration 的末尾,則在執行時會生成 NoSuchElementException。
- 如果您在空 StringTokenizer 物件上呼叫 StringTokenizer 類的 nextElement() 和 nextToken() 方法,或者如果當前位置位於 StringTokenizer 的末尾,則在執行時會生成 NoSuchElementException。
- 如果在空 Iterator/ListIterator 或當前位置位於末尾時,在 Iterator 或 ListIterator 類上呼叫 next() 方法,則在執行時會生成 Iterator/ListIterator NoSuchElementException。
- 類似地,如果在空 ListIterator 物件上呼叫 ListIterator 類的 previous() 方法,或者如果當前位置是 ListIterator 的開頭,則在執行時會生成 NoSuchElementException。
示例
讓我們考慮一個完整的一個場景的示例
import java.util.StringTokenizer; public class StringTokenizerExample{ public static void main(String args[]) { String str = "Hello how are you"; //Instantiating the StringTokenizer class StringTokenizer tokenizer = new StringTokenizer(str, " "); //Printing all the tokens System.out.println(tokenizer.nextToken()); System.out.println(tokenizer.nextToken()); System.out.println(tokenizer.nextToken()); System.out.println(tokenizer.nextToken()); //Getting the next token after reaching the end tokenizer.nextToken(); tokenizer.nextElement(); } }
執行時錯誤
Hello how are you Exception in thread "main" java.util.NoSuchElementException at java.util.StringTokenizer.nextToken(Unknown Source) at MyPackage.StringTokenizerExample.main(StringTokenizerExample.java:16)
解決方案
幾乎所有其訪問器方法導致 NoSuchElementException 的類都包含其各自的方法來驗證物件(集合、tokenizer 等)是否包含更多元素。
例如,
- Enumeration 類包含一個名為 hasMoreElements() 的方法,如果當前物件在當前位置之後包含更多元素,則返回 true(否則返回 false)。
- StringTokenizer 類包含名為 hasMoreTokens() 和 hasMoreElements() 的方法,如果當前物件在當前位置之後包含更多元素,則返回 true(否則返回 false)。
- Iterator 類包含 hasNext() 方法,如果當前迭代器在當前位置的下一個位置包含更多元素,則此方法也返回 true(否則返回 false)。
- ListIterator 類包含 hasPrevious() 方法,如果當前迭代器在當前位置之前包含更多元素,則此方法也返回 true(否則返回 false)。
示例
import java.util.StringTokenizer; public class StringTokenizerExample{ public static void main(String args[]) { String str = "Hello how are you"; //Instantiating the StringTokenizer class StringTokenizer tokenizer = new StringTokenizer(str, " "); //Printing all the tokens while(tokenizer.hasMoreTokens()) { System.out.println(tokenizer.nextToken()); } } }
輸出
Hello how are you
區別
這兩個異常的主要區別在於,當您在程式中非法位置呼叫方法時,會生成 IllegalStateException。
而當您嘗試訪問 Enumeration、Iterator、StringTokenizer 等的元素(使用訪問器方法)時,如果其中沒有更多元素,則會生成 NoElementException。
廣告