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

IlleagalStateException e NoSuchElementException in Java?

Quando si chiama un metodo in un momento illegale o inappropriato, viene generata IllegalStateException.

Ad esempio, il metodo remove() della classe ArrayList eliminerà l'ultimo elemento dopo aver chiamato il metodo next() o Previous.

  • Dopo aver eliminato l'elemento nella posizione corrente, è necessario spostarsi all'elemento successivo per eliminarlo, ovvero è possibile chiamare il metodo remove() una sola volta ogni volta che si chiama il metodo next().

  • Poiché la posizione iniziale della lista (puntatore) sarà prima del primo elemento, non è possibile chiamare questo metodo senza chiamare il metodo next().

Se si chiama il metodo remove(), altrimenti viene generata java.lang.IllegalStateException.

Esempio: spostare aCapoEliminare un elemento prima di un altro elemento

import java.util.ArrayList;
import java.util.ListIterator;
public class NextElementExample{
   public static void main(String args[]) {
      //Istanzia l'oggetto ArrayList
      ArrayList<String> list = new ArrayList<String>();
      //Riempi l'ArrayList
      list.add("mele");
      list.add("mango");
      //Ottieni l'oggetto Iterator dell'ArrayList
      ListIterator<String> it = list.listIterator();
      //Spostare l'elemento alla prima posizione
      it.remove();
   }
}

Eccezione durante l'esecuzione

Exception in thread "main" java.lang.IllegalStateException
at java.util.ArrayList$Itr.remove(Unknown Source)
at MyPackage.NextElementExample.main(NextElementExample.java:17)

Esempio: chiamare il metodo next() due volte dopo aver chiamato una volta il metodo next()

import java.util.ArrayList;
import java.util.ListIterator;
public class NextElementExample{
   public static void main(String args[]) {
      //Istanzia l'oggetto ArrayList
      ArrayList<String> list = new ArrayList<String>();
      //Riempi l'ArrayList
      list.add("mele");
      list.add("mango");
      //Ottieni l'oggetto Iterator dell'ArrayList
      ListIterator<String> it = list.listIterator();
      //Spostare l'elemento alla prima posizione
      it.next();
      it.remove();
      it.remove();
   }
}

Risultato di output

Exception in thread "main" java.lang.IllegalStateException
   at java.util.ArrayList$Itr.remove(Unknown Source)
   at MyPackage.NextElementExample.main(NextElementExample.java:17)

In questo caso, anche provare a chiamare questo metodo nel ciclo.

it.next();
while(it.hasNext()) {
   it.remove();
}

Soluzione:

In questo caso, per risolvere IllegalStateException, è necessario chiamare correttamente il metodo remove() (solo dopo aver chiamato next() una volta)

Esempio

import java.util.ArrayList;
import java.util.Arrays;
import java.util.ListIterator;
public class NextElementExample{
   public static void main(String args[]) {
      //Creazione di un oggetto ArrayList
      ArrayList<String> list = new ArrayList<String>();
      //Riempimento dell'ArrayList
      list.add("mele");
      list.add("mango");
      //Ottieni l'oggetto Iterator dell'ArrayList
      ListIterator<String> it = list.listIterator();
      //Rimozione dell'elemento senza spostarsi alla posizione iniziale
      System.out.println(Arrays.toString(list.toArray()));
      while(it.hasNext()) {
         it.next();
         it.remove();
      }  
      System.out.println(Arrays.toString(list.toArray()));
   }
}

Risultato di output

[mele, mango]
[]

Allo stesso modo, in ogni caso in cui è necessario gestire un'eccezione di stato non valido, è necessario chiamare il metodo che causa l'eccezione nella sua posizione legittima.

NosuchElementException

Se si tenta di ottenere un elemento da un oggetto vuoto o di accedere al contenuto di una collezione, un array o un altro oggetto utilizzando i metodi di accesso di Enumeration, Iterator o tokenizer (ad esempio next() o nextElement()), la tentativa di ottenere il prossimo elemento dopo aver raggiunto la fine dell'oggetto (collezione, array o altro oggetto) genera un'eccezione NoSuchElementException.

Ad esempio:

  • Se si chiama il metodo nextElement() della classe Enumeration su un oggetto Enumeration vuoto, o se la posizione attuale è alla fine di Enumeration, viene generato un'eccezione NosuchElementException durante l'esecuzione.

  • Se si chiama il metodo nextElement() o nextToken() della classe StringTokenizer su un oggetto StringTokenizer vuoto, o se la posizione attuale è alla fine di StringTokenizer, viene generato un'eccezione NosuchElementException durante l'esecuzione.

  • Se il metodo next() della classe Iterator o ListIterator viene chiamato su un Iterator / ListIterator vuoto, o se la posizione corrente è alla fine, viene generato un NoSuchElementException di Iterator / listIterator durante l'esecuzione.

  • Allo stesso modo, se si chiama il metodo previous() della classe ListIterator su un oggetto ListIterator vuoto, o se la posizione corrente è all'inizio del ListIterator, viene generato un NoSuchElementException durante l'esecuzione.

Esempio

Consideriamo un esempio completo di una situazione

import java.util.StringTokenizer;
public class StringTokenizerExample{
   public static void main(String args[]) {
      String str = "Ciao come vai tu";
      //Istanziando la classe StringTokenizer
      StringTokenizer tokenizer = new StringTokenizer(str, " ");
      //Stampando tutti i tokens
      System.out.println(tokenizer.nextToken());
      System.out.println(tokenizer.nextToken());
      System.out.println(tokenizer.nextToken());
      System.out.println(tokenizer.nextToken());
      //Ottieni il token successivo dopo aver raggiunto la fine
      tokenizer.nextToken();
      tokenizer.nextElement();
   }
}

Errore in fase di esecuzione

Ciao
come
sei
tu
Exception in thread "main" java.util.NoSuchElementException
   at java.util.StringTokenizer.nextToken(Unknown Source)
   at MyPackage.StringTokenizerExample.main(StringTokenizerExample.java:16)

Soluzione:

Quasi tutte le classi che causano NoSuchElementException tramite i loro metodi di accesso contengono metodi propri per verificare se l'oggetto (insieme, generatore di token, ecc.) contiene più elementi.

Ad esempio:

  • La classe Enumeration contiene un metodo chiamato hasMoreElements(), che restituisce true se l'oggetto corrente contiene più elementi nella posizione successiva (altrimenti restituisce false).

  • La classe StringTokenizer contiene i metodi hasMoreTokens() e hasMoreElements(), che restituiscono true se l'oggetto corrente contiene più elementi nella posizione successiva (altrimenti restituiscono false).

  • La classe Iterator contiene il metodo hasNext(), che restituisce true se l'iteratore corrente contiene più elementi nella posizione successiva (altrimenti restituisce false).

  • La classe ListIterator contiene il metodo hasPrevious(), che restituisce true se l'iteratore corrente contiene più elementi nella posizione precedente (altrimenti restituisce false).

Esempio

import java.util.StringTokenizer;
public class StringTokenizerExample{
   public static void main(String args[]) {
      String str = "Ciao come vai tu";
      //Istanziando la classe StringTokenizer
      StringTokenizer tokenizer = new StringTokenizer(str, " ");
      //Stampando tutti i tokens
      while(tokenizer.hasMoreTokens()) {
         System.out.println(tokenizer.nextToken());
      }
   }
}

Risultato di output

Ciao
come
sei
tu

Differenza

La principale differenza tra queste eccezioni è che viene generata una IllegalStateException quando chiamate un metodo in una posizione illegale del programma.

Se cercate di accedere agli elementi di Enumeration, Iterator, StringTokenizer ecc. (utilizzando i metodi di accesso), viene generata una NoElementException quando non ci sono più elementi.