English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

IlleagalStateException과 Java의 NoSuchElementException은 무엇인가요?

메서드를 불법적이거나 적절하지 않은 시간에 호출할 때 IllegalStateException이 생성됩니다.

예를 들어, ArrayList 클래스의 remove() 메서드는 next() 또는 Previous 메서드를 호출한 후 마지막 요소를 지우게 됩니다.

  • 현재 위치에서 요소를 지우면, 그 요소를 지우기 위해 다음 요소로 이동해야 합니다. 즉, next() 메서드를 호출할 때마다 remove() 메서드를 한 번만 호출할 수 있습니다.

  • 리스트(포인터)의 초기 위치가 첫 번째 요소 이전에 있기 때문에, 다음 메서드를 호출하지 않으면 이 메서드를 호출할 수 없습니다.

remove() 메서드를 호출하지 않으면 java.lang.IllegalStateException이 발생합니다.

예제: 이동하다요소 이전에 요소를 지우는 경우

import java.util.ArrayList;
import java.util.ListIterator;
public class NextElementExample{
   public static void main(String args[]) {
      //ArrayList 객체를 인스턴스화합니다
      ArrayList<String> list = new ArrayList<String>();
      //ArrayList을 채웁니다
      list.add("apples");
      list.add("mangoes");
      //ArrayList의 Iterator 객체를 얻습니다
      ListIterator<String> it = list.listIterator();
      //요소를 첫 번째 위치로 이동시킵니다
      it.remove();
   }
}

런타임 예외

thread "main"에서 Exception 발생 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[]) {
      //ArrayList 객체를 인스턴스화합니다
      ArrayList<String> list = new ArrayList<String>();
      //ArrayList을 채웁니다
      list.add("apples");
      list.add("mangoes");
      //ArrayList의 Iterator 객체를 얻습니다
      ListIterator<String> it = list.listIterator();
      //요소를 첫 번째 위치로 이동시킵니다
      it.next();
      it.remove();
      it.remove();
   }
}

출력 결과

thread "main"에서 Exception 발생 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[]) {
      //ArrayList 객체를 인스턴스화하는 것
      ArrayList<String> list = new ArrayList<String>();
      //ArrayList을 채우는 것
      list.add("apples");
      list.add("mangoes");
      //ArrayList의 Iterator 객체를 가져오는 것
      ListIterator<String> it = list.listIterator();
      //초기 위치로 이동하지 않고 요소를 제거하는 것
      System.out.println(Arrays.toString(list.toArray()));
      while(it.hasNext()) {
         it.next();
         it.remove();
      }  
      System.out.println(Arrays.toString(list.toArray()));
   }
}

출력 결과

[apples, mangoes]
[]

또한, 각 경우에 불법 상태 예외를 처리하려면, 예외를 일으키는 메서드를 합법적인 위치에서 호출해야 합니다.

NosuchElementException

빈 객체에서 요소를 가져오려고 시도하거나, Enumeration, Iterator 또는 tokenizer의 접근자 메서드(예: next() 또는 nextElement())를 사용하여 셋, 배열 또는 다른 객체의 내용을 접근하면, 객체(셋, 배열 또는 다른 객체)의 끝에 도달한 후 다음 요소를 가져오려고 시도하면 NoSuchElementException이 생성됩니다.

예를 들어서:

  • 빈 Enum 객체에 Enumeration 클래스의 nextElement() 메서드를 호출하면, 또는 Enumeration의 끝 위치에 현재 위치가 있을 때, NosuchElementException이 실행 중에 생성됩니다.

  • 빈 StringTokenizer 객체에 StringTokenizer 클래스의 nextElement()와 nextToken() 메서드를 호출하면, 또는 StringTokenizer의 끝 위치에 현재 위치가 있을 때, NosuchElementException이 실행 중에 생성됩니다.

  • Iterator나 ListIterator 클래스의 next() 메서드가 비어 있는 Iterator / ListIterator에 호출하거나 현재 위치가 끝에 있을 때 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";
      //StringTokenizer 클래스 인스턴스화
      StringTokenizer tokenizer = new StringTokenizer(str, " ");
      //모든 토큰 출력
      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();
   }
}

실행 중 오류

안녕하세요
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를 유발하는 클래스는 객체(집합, 토큰 생성기 등)가 더 많은 요소를 포함하고 있는지 확인하는 각각의 메서드를 포함하고 있습니다.

예를 들어서:

  • 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";
      //StringTokenizer 클래스 인스턴스화
      StringTokenizer tokenizer = new StringTokenizer(str, " ");
      //모든 토큰 출력
      while(tokenizer.hasMoreTokens()) {
         System.out.println(tokenizer.nextToken());
      }
   }
}

출력 결과

안녕하세요
how
are
you

차이점

이 두 예외 사이의 주요 차이점은, 프로그램에서 불법적인 위치에서 메서드를 호출할 때 IllegalStateException이 생성된다는 것입니다.

Enumeration, Iterator, StringTokenizer 등의 요소(접근자 메서드를 사용하여 접근)를 접근하려고 시도할 때, 요소가 더 이상 없을 때 NoElementException이 생성됩니다.

당신이 좋아할 만한 것