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 次查看

开启你的 职业生涯

通过完成课程获得认证

开始学习
广告

© . All rights reserved.