2015-06-09 11 views
6

Come ho capito da diversi tutorial, RuntimeExceptions in realtà non dovrebbe essere catturato, perché devono rivelare un uso inappropriato dei metodi, in particolare delle API, corretto?
Inoltre, si potrebbe supporre che il programma non è in grado di ripristinare da RuntimeExceptions.
Ora, ho riscontrato un caso in cui potevo ricevere una IndexOutOfBoundsException a causa dell'input dell'utente non valido: il programma riceve una stringa da un modulo HTML e desidera convalidarlo se contiene un numero intero.
Fondamentalmente la stringa assegnata è abbinata a un motivo e quindi viene determinata la posizione della virgola. Successivamente, è necessario esaminare la prima cifra dietro la virgola per decidere come arrotondarla correttamente. Questa è la parte critica:Gestione di RuntimeException in determinate circostanze valide?

 firstDecimalChar = formattedValue.charAt(dotPosition + 1); 

Questa affermazione genera l'eccezione, se l'utente ha immesso qualcosa come "27" A causa del fatto che questo è basato su strani input da parte dell'utente, mi sono chiesto se questa Eccezione si comporta effettivamente come un'eccezione comune (per così dire).
La maggior parte dei tutorial (ad esempio oracle) categorizza controllato Eccezioni come errori risultanti da un input non valido, ovvero il nome percorso errato in un file che deve essere aperto e con qualche correzione o un suggerimento utente è possibile recuperare da quell'errore. Lo stesso qui: si potrebbe semplicemente impostare sopra la variabile su zero, perché questo è ciò che significa quando qualcuno inserisce "27". -> "27.0"

È quella cattura e specificare requisito davvero così severo? Naturalmente, si può verificare in anticipo se la posizione non è fuori campo, ma la mia domanda è se c'è una linea retta tra spuntata e eccezioni deselezionate. Mi chiedo se ci siano degli svantaggi tecnici perché le eccezioni dovrebbero essere evitate il più spesso possibile. (Qualcuno ha menzionato JVM-overhead, ma è significativo?)

Penso di aver bisogno di chiarimenti più approfonditi qui, perché la maggior parte dei tutorial non mi convincono: "semplicemente non dovresti farlo". Poiché in questo caso ritengo che questa eccezione si comporti come una selezionata dall'eccezione da cui è facile eseguire il ripristino.

Nota: Nel mio codice controllo se la posizione della stringa è valida o meno e non rilevo l'eccezione - quindi non fa parte di questa domanda:) Ma questo caso mi tiene occupato, ancora.

risposta

6

È quella cattura e specificare il requisito davvero così severo?

No, penso che sia ok per rilevare le eccezioni non controllate (RuntimeExceptions) in determinate situazioni.

Ad esempio, se un utente inserisce un numero, penso che sia perfettamente bene fare

double i; 
try { 
    i = Double.parseDouble(userInput); 
} catch (NumberFormatException e) { 
    addValidationError("Entered number is not valid: " + userInput); 
} 

Se un'eccezione è inaspettato e corrisponde ad un errore nel codice, non si preoccupano di cattura è (o prendi il livello più alto, come ad esempio in handleRequest o altro, e restituisci un errore 500, ad esempio). D'altra parte, se si può prevedere che venga lanciata un'eccezione (ed è problematico utilizzare strutture di controllo ordinarie come le dichiarazioni if per coprire tali casi, ad esempio nell'esempio NumberFormatException sopra) catturarlo e gestirlo.

Come succede, RuntimeExceptions spesso corrispondono al programmatore errori, e dicendo "non prendere RuntimeExceptions" probabilmente può essere visto come una buona approssimazione di quello che per la cattura e non per la cattura.

Quando uno sviluppatore decide se estendere o ExceptionRuntimeException lui/lei sarà pensare se è ragionevole forza i clienti a dichiarare tiri clausole/intercettare l'eccezione. In alcuni casi, un'eccezione può essere dovuta sia a un errore di programmazione sia a un errore di "normale funzionamento". In questi casi è un po 'scortese forzare lo throws/catch sui client, ed è più appropriato renderlo un RuntimeException. Nel codice client, in cui l'eccezione viene effettivamente utilizzata per indicare l'errore "operazione normale", è comunque opportuno prenderla.

questione connessa (ma chiuso in primo luogo come opinione-based): stackoverflow.com/questions/24344511/why-is-catching-a-runtimeexception-not-considered-a-good-programming-practice

+0

Non mi piace che Java non abbia un modo per verificare se una stringa è un intero senza generare un'eccezione. La validazione delle stringhe non è un caso/problema eccezionale. Dovrebbero portare TryParse in Java di C#. –

+1

@RoyT. Una semplice regex ti permette di controllare se 'String' è un numero intero. ('" -? \\ d + (\\. \\ d +)? "' – CKing

+0

@ChetanKinger true, anche se sarebbe bello se tutti i tipi primitivi avessero un controllo integrato, ma abbiamo bisogno di lottare con espressioni rege e roba. la maggior parte dei casi significa che i programmatori sono piuttosto pigri e usano solo un try catch :). –

2

Come ho capito da diverse esercitazioni, RuntimeExceptions sono in realtà in realtà non dovrebbe essere catturato, perché devono rivelare uso inappropriato dei metodi, in particolare le API, corretto?

Non proprio. Si può sempre prendere un RuntimeException e avvolgerlo in un controllato Exception e throw indietro al chiamante per loro di decidere se uccidere l'app o avvolgere l'errore in un formato che può essere compreso dall'utente

Esempio:

try { 
    //read parameters 
    String processType = args[9]; 
    String username = args[11]; 
    //read more parameters.. 
} catch (ArrayIndexOutOfBoundsException e) { 
    throw new InvalidInputException("Wrong number of input parameters passed. See usage notes"+e); 
} 
+0

questa risposta mi aiuta, dopo tutto: D Questa è in effetti una buona soluzione per rimanere conformi con [Dichiarazione di Oracle] (https://docs.oracle.com/javase/tutorial/essential/exceptions/catchOrDeclare.html) che _checked_ Sono previste eccezioni per indicare problemi con l'input dell'utente. Risolve l'ambivalenza di un RuntimeException quando viene attivato a causa di un I/O inappropriato perché lo converte –

1

Penso che un'eccezione di runtime significhi qualcosa che in realtà non dovrebbe mai accadere durante l'esecuzione di un programma. Ad esempio, IOException non è un'eccezione di runtime: una IOException si verifica perché qualcosa al di fuori del controllo del programma (il filesystem in questo caso) non funziona correttamente.

Tuttavia, una ArrayIndexOutOfBoundsException si verifica mentre il programma ha il controllo completo. Quindi è una RuntimeException. Significa che il programmatore ha fatto qualcosa di sbagliato. Ad esempio un calcolo errato di un indice di array.

Immaginiamo un programma che non interagisce affatto con il mondo esterno (nessun IO, ecc.) Questo programma non dovrebbe mai generare un'eccezione perché ha il completo controllo di tutto ciò che accade. Se genera un'eccezione significa che il programmatore ha fatto qualcosa di sbagliato (o era molto pigro).

Nota: ho completamente riscritto questa risposta perché prima non ho visto la nota alla fine della domanda :)

+0

Sono d'accordo, che un programma senza IO non dovrebbe generare eccezioni perché sa quali valori ci si aspetta dai metodi:) Ma il mio caso presume , che IO è necessario ed è in realtà il motivo per cui improvvisamente un'eccezione diventa un risultato possibile, a tutti. L'utente potrebbe inserire qualcosa che non avrei mai prodotto con metodi, ad es. "27." Poiché non si tratta né di un punto di virgola mobile né di un intero, che avrei potuto convertire in una stringa ^^ Questo è ciò che mi ha portato alla conclusione che una RuntimeException deve improvvisamente essere trattata come una _checked_, a causa della sua dipendenza dal utente –

+0

Penso che un'eccezione ArrarayIndexOutOfBoundsException non sia dovuta all'input dell'utente, ma a un programmatore pigro che non controlla l'input dell'utente. E quindi dovrei essere un'eccezione di runtime e non dovrebbe essere catturato. Invece dovresti correggere il codice (aggiungendo i controlli) :). La ragione per cui IO harddisk è una CheckedException è che, ad esempio, non puoi controllare se qualcuno cancella un file mentre lo stai leggendo. Tuttavia, hai il pieno controllo sulle variabili ottenute usando IO. –

1

Alcuni metodi di esecuzione o di terze parti (come Integer.parseInt) segnalare l'errore di validazione attraverso eccezione . Se abbiamo bisogno di questa funzionalità di convalida, dobbiamo rilevare l'eccezione.

Probabilmente sarebbe meglio avere qualcosa come Integer.isValid(String x) ma anche abbondanti sostituzioni di librerie standard fatte in casa sono problematiche.

+0

quindi pensi che, in realtà, questo problema possa essere visto come un'implementazione inadeguata, vero? È interessante, tbh. Molte persone hanno dichiarato che altre lingue sono in grado di effettuare tali convalide. Quindi forse è vero che i programmatori che usano _unchecked_ Exceptions sono davvero un po 'pigri, anche se lavorano a Oracle, perché sembra che sarebbero stati in grado di inventare qualcosa di meglio ^^ –