Perché è necessario "genera eccezione" quando si chiama una funzione?


98
class throwseg1
{
    void show() throws Exception
    {
        throw new Exception("my.own.Exception");
    }

    void show2() throws Exception  // Why throws is necessary here ?
    {
        show();
    }

    void show3() throws Exception  // Why throws is necessary here ?
    {
        show2();
    }

    public static void main(String s[]) throws Exception  // Why throws is necessary here ?
    {
        throwseg1 o1 = new throwseg1();
        o1.show3();
    }
}

Perché i rapporti compilatore che i metodi show2(), show3()e main()hanno

eccezione non segnalata Eccezione che deve essere rilevata o dichiarata per essere generata

quando rimuovo throws Exceptionda questi metodi?


2
@PaulTomblin main può certamente essere dichiarato per lanciare un'eccezione. In caso affermativo, la JVM si spegnerà. Questo è il più vicino all'ignorarlo quanto il compilatore consentirà.
Taymon

Quando viene generato il metodo chiamato ( Methdod1 ) Exception, dobbiamo definire il metodo chiamante ( Method2 ) con throws Exception; se non stiamo passando quell'eccezione nel metodo chiamante. Lo scopo di ciò è di avvisare il metodo chiamante ( Method3 ) di Method2 che un'eccezione può essere lanciata da Method2 e dovresti gestirla qui, altrimenti potrebbe interrompere il tuo programma.
Rito

Allo stesso modo, se Method3 non sta gestendo l'eccezione nel suo corpo, allora doveva definire throws Exceptionnella sua definizione di metodo per dare un avvertimento al suo metodo chiamante. estensione del commento precedente
Rito

Risposte:


144

In Java, come forse saprai, le eccezioni possono essere suddivise in due: una che necessita della throwsclausola o che deve essere gestita se non ne specifichi una e un'altra che non la specifica. Ora, guarda la figura seguente:

inserisci qui la descrizione dell'immagine

In Java, puoi lanciare qualsiasi cosa che estenda la Throwableclasse. Tuttavia, non è necessario specificare una throwsclausola per tutte le classi. In particolare, le classi che sono una Erroro RuntimeExceptiono una qualsiasi delle sottoclassi di questi due. Nel tuo caso Exceptionnon è una sottoclasse di un Erroro RuntimeException. Quindi, è un'eccezione controllata e deve essere specificata nella throwsclausola, se non gestisci quella particolare eccezione. Ecco perché avevi bisogno della throwsclausola.


Dal tutorial Java :

Un'eccezione è un evento, che si verifica durante l'esecuzione di un programma, che interrompe il normale flusso delle istruzioni del programma.

Ora, come sai, le eccezioni sono classificate in due: selezionate e deselezionate. Perché queste classificazioni?

Eccezione selezionata: vengono utilizzati per rappresentare problemi che possono essere risolti durante l'esecuzione del programma. Di solito non sono colpa del programmatore. Ad esempio, un file specificato dall'utente non è leggibile o nessuna connessione di rete disponibile, ecc., In tutti questi casi, il nostro programma non ha bisogno di uscire, invece può eseguire azioni come avvisare l'utente o andare in fallback meccanismo (come il funzionamento offline quando la rete non è disponibile), ecc.

Eccezioni non selezionate: possono essere nuovamente divise in due: Errori e RuntimeExceptions. Uno dei motivi per cui sono deselezionati è che sono numerosi e la necessità di gestirli tutti ingombrerà il nostro programma e ne ridurrà la chiarezza. L'altro motivo è:

  • Eccezioni di runtime: di solito si verificano a causa di un errore del programmatore. Ad esempio, se si verifica una ArithmeticExceptiondivisione per zero o si verifica un ArrayIndexOutOfBoundsException, è perché non siamo abbastanza attenti nella nostra codifica. Di solito si verificano a causa di alcuni errori nella logica del nostro programma. Quindi, devono essere cancellati prima che il nostro programma entri in modalità di produzione. Sono deselezionate nel senso che il nostro programma deve fallire quando si verifica, in modo che noi programmatori possiamo risolverlo al momento dello sviluppo e del test stesso.

  • Errori: gli errori sono situazioni dalle quali normalmente il programma non può ripristinarsi. Ad esempio, se si StackOverflowErrorverifica un , il nostro programma non può fare molto, come aumentare la dimensione dello stack di chiamata della funzione del programma. Oppure, se si OutOfMemoryErrorverifica un problema, non possiamo fare molto per aumentare la quantità di RAM disponibile per il nostro programma. In questi casi, è meglio uscire dal programma. Ecco perché sono deselezionate.

Per informazioni dettagliate vedere:


quello che ho ottenuto dalla tua risposta è che la classe Error e le sue sublaclassi e la classe RuntimeException e le sue sottoclassi, rientrano in un'eccezione non controllata (come System.out.println (5/0); non è necessario lanciare perché è un eccezione di runtime ma possiamo comunque applicare try catch) e la classe Exception è selezionata, quindi dobbiamo dichiarare la clausola throws in quel metodo e in ogni metodo che la chiama
nr5

Ancora una domanda: se le eccezioni sono classificate in deselezionate e controllate, specialmente quelle non spuntate (errori di runtime) per evitare più errori in fase di compilazione?
nr5

@Jomoos - Supponiamo che il codice all'interno di un metodo generi IOException. Quindi, va bene mettere "throws Exception" nella dichiarazione del metodo?
MasterJoe

Oh. Capisco adesso. c'è un'eccezione alle regole della gerarchia delle eccezioni. Fa. Perfetto. Senso. Grazie Java.
JJS

25

Java richiede che tu gestisca o dichiari tutte le eccezioni. Se non stai gestendo un'eccezione utilizzando un blocco try / catch, deve essere dichiarato nella firma del metodo.

Per esempio:

class throwseg1 {
    void show() throws Exception {
        throw new Exception();
    }
}

Dovrebbe essere scritto come:

class throwseg1 {
    void show() {
        try {
            throw new Exception();
        } catch(Exception e) {
            // code to handle the exception
        }
    }
}

In questo modo puoi sbarazzarti della dichiarazione "throws Exception" nella dichiarazione del metodo.


7
Tutte le eccezioni che non sono sottoclassi di RuntimeException, cioè.
yshavit

se c'è qualche altra classe come l'eccezione che viene controllata?
nr5

1
Cosa intendi? Poiché tutti gli oggetti eccezione hanno "Eccezione" come classe di base, se catturi un oggetto "Eccezione" (come nel mio esempio), catturerà qualsiasi eccezione generata. Per essere più specifici (poiché eccezioni diverse probabilmente richiederanno modi diversi di gestire le cose) dovresti avere più blocchi catch.
jebar8

se dovessi dire che le eccezioni controllate devono essere gestite in fase di compilazione e catturate in fase di esecuzione. Ho ragione ? se sì, allora formulare la stessa frase per Eccezione non controllata sarebbe?
nr5

@ jebar8 - stai confondendo Java con .NET - in Java, gli oggetti lanciabili devono ereditare Throwable( Exceptionfunziona anche l' ereditarietà , perché si estende Throwable, ma non è richiesto).
BrainSlugs83

5

La throws Exceptiondichiarazione è un modo automatizzato per tenere traccia dei metodi che potrebbero generare un'eccezione per motivi previsti ma inevitabili. La dichiarazione è in genere specifica sul tipo o sui tipi di eccezioni che possono essere generate come throws IOExceptiono throws IOException, MyException.

Tutti abbiamo o alla fine scriveremo codice che si arresta in modo imprevisto e segnala un'eccezione a causa di qualcosa che non avevamo previsto prima di eseguire il programma, come la divisione per zero o l'indice fuori dai limiti. Poiché gli errori non erano previsti dal metodo, non è stato possibile "intercettarli" e gestirli con una clausola try catch. Anche gli utenti ignari del metodo non sarebbero a conoscenza di questa possibilità e anche i loro programmi si fermerebbero.

Quando il programmatore sa che possono verificarsi alcuni tipi di errori ma desidera gestire queste eccezioni al di fuori del metodo, il metodo può "lanciare" uno o più tipi di eccezioni al metodo chiamante invece di gestirli. Se il programmatore non ha dichiarato che il metodo (potrebbe) lanciare un'eccezione (o se Java non ha la capacità di dichiararla), il compilatore non potrebbe saperlo e spetterebbe al futuro utente del metodo sapere, catturare e gestire eventuali eccezioni che il metodo potrebbe generare. Poiché i programmi possono avere molti livelli di metodi scritti da molti programmi diversi, diventa difficile (impossibile) tenere traccia di quali metodi potrebbero generare eccezioni.

Anche se Java ha la capacità di dichiarare eccezioni, puoi comunque scrivere un nuovo metodo con eccezioni non gestite e non dichiarate, e Java lo compilerà e potrai eseguirlo sperando per il meglio. Ciò che Java non ti consente di fare è compilare il tuo nuovo metodo se utilizza un metodo che è stato dichiarato come lanciare eccezioni, a meno che tu non gestisca le eccezioni dichiarate nel tuo metodo o dichiari che il tuo metodo lancia lo stesso eccezioni o se ci sono più eccezioni, puoi gestirne alcune e lanciare le altre.

Quando un programmatore dichiara che il metodo genera un tipo specifico di eccezione, è solo un modo automatico per avvisare gli altri programmatori che utilizzano il metodo che un'eccezione è possibile. Il programmatore può quindi decidere di gestire l'eccezione o trasmettere l'avviso dichiarando che anche il metodo chiamante genera la stessa eccezione. Poiché il compilatore è stato avvertito che l'eccezione è possibile in questo nuovo metodo, può controllare automaticamente se i futuri chiamanti del nuovo metodo gestiscono l'eccezione o la dichiarano e impongono che si verifichi l'una o l'altra.

La cosa bella di questo tipo di soluzione è che quando il compilatore segnala Error: Unhandled exception type java.io.IOException, fornisce il file e il numero di riga del metodo che è stato dichiarato per generare l'eccezione. Puoi quindi scegliere di passare semplicemente il dollaro e dichiarare che anche il tuo metodo "genera IOException". Questa operazione può essere eseguita fino al metodo principale, dove causerebbe l'arresto del programma e segnalerebbe l'eccezione all'utente. Tuttavia, è meglio catturare l'eccezione e affrontarla in un modo carino, ad esempio spiegando all'utente cosa è successo e come risolverlo. Quando un metodo rileva e gestisce l'eccezione, non deve più dichiarare l'eccezione. Il dollaro si ferma qui, per così dire.


4

Exceptionè una classe di eccezione controllata. Pertanto, qualsiasi codice che chiama un metodo che dichiara che throws Exceptiondeve gestirlo o dichiararlo.


Ogni metodo nella catena viene dichiarato per generare un'eccezione, incluso main. Allora dov'è il problema?
Paul Tomblin

@PaulTomblin sto chiedendo che è questo il motivo per cui è necessario scrivere genera un'eccezione nelle funzioni chiamanti, chiamando una funzione che genera un'eccezione
nr5

Ok, non ho capito perché stavi chiedendo di un errore del compilatore che non stavi effettivamente ottenendo dal codice che hai pubblicato. È uno strano modo di chiedere.
Paul Tomblin

0
package javaexception;


public class JavaException {
   void show() throws Exception
    {
        throw new Exception("my.own.Exception");
    }

void show2() throws Exception  // Why throws is necessary here ?
{
    show();
}

void show3() throws Exception  // Why throws is necessary here ?
{
    show2();
}
public static void main(String[] args) {

   JavaException a = new JavaException();

   try{
   a.show3();
   }catch(Exception e){
       System.out.println(e.getMessage());
   }
}

Solo piccoli cambiamenti nel tuo programma. Quello che sembra essere frainteso da molti riguardo al problema principale, è che ogni volta che lanci un'eccezione devi gestirla, non è necessario nello stesso posto (es. Metodo show1,2,3 nel tuo programma) ma devi prima chiamare il metodo all'interno del "main". in una parola, c'è "lancio", deve esserci "cattura / prova", anche se non è lo stesso metodo in cui avviene l'eccezione.


0
void show() throws Exception
{
    throw new Exception("my.own.Exception");
}

Poiché è presente un'eccezione controllata nel metodo show (), che non viene gestita in quel metodo, utilizziamo la parola chiave throws per propagare l'eccezione.

void show2() throws Exception //Why throws is necessary here ?
{
show();
}

Dato che stai usando il metodo show () nel metodo show2 () e hai propagato l'eccezione almeno, dovresti gestirla qui. Se non stai gestendo l'eccezione qui, allora stai usando la parola chiave throws. Quindi questo è il motivo per utilizzare la parola chiave throws alla firma del metodo.


0

Se si propaga l'eccezione dichiarando la direttiva throws nella firma del metodo corrente, allora da qualche parte nella riga o nello stack di chiamate deve essere utilizzato un costrutto try / catch per gestire l'eccezione.


Questo commento dovrebbe essere aggiunto alla sezione commenti in quanto non fornisce una risposta verificabile o un esempio di una. - stackoverflow.com/help/how-to-answer
Paul Dawson

-1

Fondamentalmente, se non gestisci l'eccezione nello stesso punto in cui la lanci, puoi usare "genera eccezione" nella definizione della funzione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.