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。

更新於: 2019年9月19日

164 次檢視

開啟你的 職業生涯

透過完成課程獲得認證

開始學習
廣告