View Full Version : [Java] contrarre catch
questa è una banalità sintattica: mettiamo che devo chiamare un metodo con una clausola throws che non finisce mai (cioè un metodo che lancia molte eccezioni), e mettiamo che le voglio catturare tutte subito con un try attorno alla chiamata; infine mettiamo anche che tutti quanti i catch di quel try hanno lo stesso identico codice, quale potrebbe essere ad es. un semplice "return false;". la domanda è: sintatticamente parlando è possibile contrarre tutti i catch in un solo catch che piglia tutte le eccezioni? lo scopo è ovviamente quello di non scrivere mille volte lo stesso codice di handling.
sono a conoscenza del fatto che è possibile sfruttare il polimorfismo catturando la classe a monte anziché quella specifica (cioè catturo semplicemente Exception) ma ovviamente è una soluzione brutta perché filtra anche eccezioni che non voglio filtrare.
sono a conoscenza del fatto che è possibile sfruttare il polimorfismo catturando la classe a monte anziché quella specifica (cioè catturo semplicemente Exception) ma ovviamente è una soluzione brutta perché filtra anche eccezioni che non voglio filtrare.Non è detto. Immaginiamo che ci sia un metodo() che ha come throws: IOException, InterruptedException, SQLException, ClassNotFoundException (è solo un esempio ;) ). Supponiamo che IOException non voglio gestirla ma magari farla gestire "più sopra".
Soluzione 1:
try
{
metodo ();
}
catch (IOException ioe)
{
throw ioe;
}
catch (Exception e)
{
// gestisci il resto
}
Soluzione 2:
try
{
metodo ();
}
catch (Exception e)
{
if (e instanceof IOException)
throw e;
// gestisci il resto
}
d'accordo, ma la soluzione è brutta comunque perché il "// gestisci il resto" gestisce anche tutte le eccezioni unchecked (che derivano sempre da Exception, come le altre). se per esempio il codice di metodo() è buggato e in alcuni casi spara una NullPointerException, io voglio che la NullPointerException arrivi a monte. ciò che io speravo è che a livello sintattico esistesse una sorta di:
try
{
metodo();
}
catch (Exception1 e1, Exception2 e2, ecc. ecc.)
{
// gestione unica per tutte quelle che voglio catturare
}
piuttosto che:
try
{
metodo();
}
catch (Exception1 e1)
{
// gestione Exception1, identica a tutte le altre
}
catch (Exception2 e2)
{
// gestione Exception2, identica a tutte le altre
}
.
.
.
insomma volevo solo evitare di scrivere N volte lo stesso codice di handling :)
d'accordo, ma la soluzione è brutta comunque perché il "// gestisci il resto" gestisce anche tutte le eccezioni unchecked (che derivano sempre da Exception, come le altre). se per esempio il codice di metodo() è buggato e in alcuni casi spara una NullPointerException, io voglio che la NullPointerException arrivi a monte.Per quanto riguarda la sintassi non c'è alcuna scappatoia, il parametro formale del catch può essere uno solo.
Se a te interessa che le eccezioni unchecked vengano gestite a monte, allora ripropongo la mia soluzione 2, ti basta testare:
if (e instanceof RuntimeException)
throw e;Credo che sia la soluzione migliore, visto che vuoi avere un unico codice per il catch. Di più non saprei dirti, anche perché non credo che ci siano altre possibilità.
ullallà, non conoscevo la classe RuntimeException: non sapevo che tutte le eccezioni unchecked venissero da lì. questo thread mi è stato utile :)
per quanto riguarda la domanda iniziale, penso che la soluzione migliore per non scrivere N volte lo stesso codice di handling sia quella di racchiunderlo tutto in un metodo di handling chiamato N volte dagli N catch.
Ciao. La lettura del thread mi ha interessato e portato alla seguente soluzione, meno semplice ma più generale delle soluzioni precedenti:
import java.io.IOException;
interface MyThrowables {}
class MyUncheckedException
extends ClassNotFoundException
implements MyThrowables {
}
class MyCheckedException
extends IOException
implements MyThrowables {
}
class MyError
extends NoClassDefFoundError
implements MyThrowables {
}
public class TestMyThrowables {
public static void throwsMyThrowables() throws Throwable {
throw new Error();
}
public static void main(String[] args) throws Throwable {
try {
throwsMyThrowables();
} catch(Throwable t) {
if(t instanceof MyThrowables) {
System.out.println("Caught an MyThrowables");
} else {
System.out.println("Thrown not an MyThrowables");
throw(t);
}
}
}
}
Il gruppo di eccezioni o errori (in generale Throwable) che vuoi gestire in modo unico sono accomunati dall' interfaccia MyThrowables.
Il prezzo è dover estendere ogni classe Throwable che ti interessa (ClassNotFoundException, IOException, NoClassDefError, ...).
Se c'è un metodo che dichiara il rilascio di 17 eccezioni diverse intercetti le 17 eccezioni una per una. Un instanceof all'interno di un catch è come dire "volevo usare C ma mi hanno costretto...". :D
Mi correggo da solo. Ho divagato.
Non risolve per niente il problema iniziale.
Sorry :)
Se c'è un metodo che dichiara il rilascio di 17 eccezioni diverse intercetti le 17 eccezioni una per una. Un instanceof all'interno di un catch è come dire "volevo usare C ma mi hanno costretto...". :D il problema è che il metodo che rilascia la svaria di eccezioni non lo posso modificare (è di Java ^^) e al mio programma non interessa gestire differentemente i casi uno per uno: lui ci prova, poi se qualcosa fallisce return false; e amen :p
tanto l'utente non è che si può pretendere che capisca in dettaglio il motivo del failure... :D
So che è scomodissimo, noioso ed esteticamente terribile ma le eccezioni vanno prese e gestite singolarmente perchè dal punto di vista di chi le cattura esse valgono in quanto segnale di uno specifico sintomo. Generalizzando il "catch" vanifichi la specializzazione dell'allarme. E' qui la differenza tra un'eccezione e il famigerato valore restituito dalle funzioni C.
Naturalmente si fa un atto di fede: chi ha dichiarato il rilascio di quelli mille eccezioni sapeva ciò che stava dicendo. Ognuna di quelle eccezioni segnala un problema autonomo non comprensibile attraverso uno dei supertipi di quell'eccezione.
Ripeto, sintatticamente è terribile. Ti ammazzi di parentesi, per non parlare dei finally in cui invochi un metodo che rilascia un'altra eccezione. Ma la programmazione orientata agli oggetti, a mio sommessissimo avviso, è una questione non di forme ma di significati. E il pregio di Java non è quello di essere formalmente elegante o sintetico ma semanticamente (ok, vinco il premio per il peggior avverbio della settimane) espressivo.
ma capisco benissimo la questione e non avrei assolutamente voluto che quel metodo di quella classe di Java fosse stato fatto in maniera minimamente diversa o che avesse accomunato anche due sole delle eccezioni che lancia.
il mio specifico problema è che io specificamente non ho interesse a gestire tutti quei casi singolarmente perché mi basta che la gestione sia sempre la stessa per tutti. solo in questo caso però! poi, in futuro, quando magari farò un altro programma più decente :stordita: allora mi passerà per la testa di restituire all'utonto un feedback diverso per ciascuno di quei casi, e quindi mi sarà utilissimo che ciascuno di quei casi sia rappresentato da un'eccezione diversa. va benissimo.
in conclusione, la questione che sollevavo in questo thread era banalissima: siccome il try/catch che ho fatto ha lo stesso identico codice in tutti i catch (un return false, ma poteva andare peggio), non è che tante volte c'era per caso modo di scriverlo una volta sola anziché N volte? :stordita:
risposta: no, se non semplicemente mettendo quel codice in un metodo e chiamando il metodo N volte (soluzione ovviamente non attuabile nel caso di un semplice return false). alla mia modestissima opinione questa pare una lieve carenza sintattica di Java, tutto qui ^^
ora che abbiamo oltremodo chiarito le nostre reciproche posizioni, non cominciamo con le solite cose da anti-flame come "certo hai ragione tu, ma è anche così" - "no, hai più ragione tu e ti voglio bene, ma è anche colà" :D
Mi Immetto Anche io nella discussione.
Allora io nn sono per nulla d'accordo agli instanceOf ma comunque ci sono metodi per gestire le eccezioni multiple anche in un solo catch o la massimo in due per esempio:
try {
metodo();
} catch(RuntimeException e) {
throw e;
} catch(Exception e) {
//gestione di tutte le eccezioni dichiarate!
}
in questo modo rimando tutte le RuntimeException e catturo le eccezioni dichiarate e le gestisco con un solo catch.
Mi Immetto Anche io nella discussione.
Allora io nn sono per nulla d'accordo agli instanceOf ma comunque ci sono metodi per gestire le eccezioni multiple anche in un solo catch o la massimo in due per esempio:
try {
metodo();
} catch(RuntimeException e) {
throw e;
} catch(Exception e) {
//gestione di tutte le eccezioni dichiarate!
}
E' un po' la stessa idea di andbin... ;)
vBulletin® v3.6.4, Copyright ©2000-2026, Jelsoft Enterprises Ltd.