View Full Version : [JAVA] gestione degli errori
Ciao a tutti.
Mi trovo ora nell'imparare una delle cose, per quanto mi riguarda, più difficili.
Come gestire gli errori: non riesco a capire come propagarli.
vorrei fare una cosa tipo quella che uso in VB6:
function getRecordSet(ByVal strSQL as String, ByRef rs as Recordset) as Boolean
On Error goto Gest_Err_Label
....
....
la funzione restituisce TRUE o FALSE a seconda se il RS viene creato o meno, in rs ho il recordSet creato in quanto viene passato per riferimento e il codice
Dim rsMyRS as new ADODB.Recordset
if getRecordSet("query sql", rsMyRS) then
codice per gestire il RS.
else
err.raise richiama l'errore generato dalla funzione cosi non fa il codice successivo!
endif
gestisce tutto.
in java invece ho un po di difficoltà:
il codice
LinkedList<String[]> cmb = db.rsToLL("select genere from TABELLA_INESISTENTE order by genere");
DefaultListModel lm = new DefaultListModel();
for (String[] combo : cmb) {
lm.addElement(combo[0]);
}
genera l'errore nella classe dove c'è il metodo rsToLL "net.ucanaccess.jdbc.UcanaccessSQLException: user lacks privilege or object not found: TABELLA_INESISTENTE", ma poi continua a fare anche il DefaultListModel, generando altri errori di "Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException" ecc.ecc.
Come faccio a terminare l'esecuzione, rimandandola, ....diciamo all'ultima parentesi graffa che chiude tutto il codice?
la classe del metodo rsToLL è scritta cosi:
....
....
public LinkedList rsToLL(String strSQL){
LinkedList<String[]> rsOUT = new LinkedList<>();
try {
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery(strSQL);
ResultSetMetaData rsmd= rs.getMetaData();
while (rs.next()){
String element[]=new String[rsmd.getColumnCount()];
for (int i=1;i<=rsmd.getColumnCount();i++){
element[i-1]=rs.getString(i);
}
System.out.println();
rsOUT.addLast(element);
}
rs.close();
s.close();
return rsOUT;
} catch (SQLException ex) {
ex.printStackTrace();
//JOptionPane.showMessageDialog(null, ex, "", JOptionPane.ERROR_MESSAGE);
return null;
}
}
....
....
spero di essermi spiegato.
ciao tagan
Daniels118
21-11-2014, 15:19
Devi prima di tutto fare una scelta, ovvero se gestire l'errore con un'eccezione o ritornando un valore simbolico. Da come hai impostato il metodo rsToLL (restituisci null in caso di errore) sembra che tu voglia percorrere la seconda strada:
LinkedList<String[]> cmb = db.rsToLL("select genere from TABELLA_INESISTENTE order by genere");
if (cmb != null) {
DefaultListModel lm = new DefaultListModel();
for (String[] combo : cmb) {
lm.addElement(combo[0]);
}
}
Oppure avresti potuto propagare l'eccezione, questo è uno dei modi possibili:
public LinkedList rsToLL(String strSQL) throws Exception {
try {
...
} catch (SQLException ex) {
...
throw ex;
}
}
Oppure avresti potuto propagare l'eccezione, questo è uno dei modi possibili:
public LinkedList rsToLL(String strSQL) throws Exception {
try {
...
} catch (SQLException ex) {
...
throw ex;
}
}
perfetto. questo è quello che mi interessava. come propagare l'errore. modificherò la classe con operazioni al DB in questo modo.
Un ultima cosa: se volessi creare una classe per gestire ogni tipo di eccezione, sia quelle generate dal linguaggio, che quelle generate da me, dal mio codice, come posso capire il tipo di eccezione?
mi spiego meglio con un esempio:
try{
//codice che può generare eccezione, esempio SQL
}
catch(Exception ex){
new GestioneErrori(ex);
}
if (condizione_errore_digitazione){
new GestioneErrori(new Exception("errore o avvertimento generato da me"));
}
la classe è
public class GestioneErrori extends Exception {
public GestioneErrori(Exception ex){
switch (ex.qualcosa){
case [tipo "IOException"]:
//fai qualcosa
//mostra messaggio di errore
JOptionPane.showMessageDialog(null, ex, null, JOptionPane.ERROR_MESSAGE);
break;
case [tipo "SQLException"]:
//fai qualcos'altro
break;
default:
//mostra messaggio di avvertimento
JOptionPane.showMessageDialog(null, ex, null, JOptionPane.WARNING_MESSAGE);
}
}
}
si può fare una cosa del genere? si può capire il tipo di eccezione, passando al costruttore una eccezione generica?
grazie.
Daniels118
23-11-2014, 10:04
Certamente. Puoi fare così:
try {
//Codice che genera eccezioni
} catch (TipoEccezione1 e1) {
...
} catch (TipoEccezione2 e2) {
...
}
Fai attenzione però, che il catch TipoEccezione1 cattura non solo le eccezioni di quel tipo, ma anche tutte le eccezioni che ereditano da esso. Se ad esempio TipoEccezione2 estende TipoEccezione1, il catch TipoEccezione2 non verrà mai eseguito.
Ricordati inoltre di utilizzare le eccezioni solo per gestire quelle condizioni che sono effettivamente anomale, e non per gestire situazioni normali.
Certamente. Puoi fare così:
try {
//Codice che genera eccezioni
} catch (TipoEccezione1 e1) {
...
} catch (TipoEccezione2 e2) {
...
}
Questo sistema lo conosco. volevo evitare di disseminare il codice di molte catch e richiamare una sola classe che potesse gestirle tutte, ma una volta passata l'eccezione (Exception ex), non riesco più a capire di che tipo è.
a questo punto, mi conviene creare nella classe che gestisce gli errori, diversi metodi che vengono richiamati nei catch disseminati nel codice.
Ricordati inoltre di utilizzare le eccezioni solo per gestire quelle condizioni che sono effettivamente anomale, e non per gestire situazioni normali.
ok. per questi casi ho creato un'altra classe per le notifiche all'utente.
grazie. ciao
tagan
Daniels118
24-11-2014, 12:50
Puoi usare l'operatore instanceof per determinare se un oggetto è un'istanza di una determinata classe (o di una classe che eredita da essa), però la gestione con i catch è molto più elegante, non capisco perché vorresti evitarla.
Edit: rileggendo la tua affermazione, forse ciò che vorresti evitare è di avere molte classi per le eccezioni, ebbene puoi farne una sola con un attributo "tipo" che andrai a valorizzare in modo opportuno.
sottovento
24-11-2014, 13:44
Puoi anche fare:
try
{
....
}
catch (TipoEccezione1 | TipoEccezione2 | ... | TipoEccezioneN)
{
}
Sul tipo delle eccezioni vale quello che ha detto Daniels118: non puoi mettere in un catch simile una eccezione se estende o viene estesa da un'altra gia' presente.
Infine: evita sempre di fare il catch(Exception)
Edit: rileggendo la tua affermazione, forse ciò che vorresti evitare è di avere molte classi per le eccezioni, ebbene puoi farne una sola con un attributo "tipo" che andrai a valorizzare in modo opportuno.
ho fatto proprio una cosa del genere, ma utilizzando il metodo getClass e getName per capire che tipo di eccezione sia. dopo un po di tentativi sono riuscito a fare questo:
public class GestisciEccezioni {
public GestisciEccezioni(Exception ex, Object obj){
switch (ex.getClass().getSimpleName()){
case "FileNotFoundException":
obj.getClass().getSimpleName() //ho il nome della JFrame o della classe che ha generato l'errore; volendo potrei passare anche il nome del metodo in errore.
break;
case "RuntimeException":
//faccio altre cose
case "SQLException":
//faccio altre cose
case "NullPointerException":
//faccio altre cose
default:
......
}
}
}
il codice pericoloso invece viene gestito cosi i tutte le classi del programma.
try{
......
}
catch (Exception ex){
new GestisciEccezioni(ex,this)
}
in questo modo, trasformo in eccezioni anche situazioni anomale di procedure importanti.
un altra classe simile invece, è GestisciAvvertimenti, che sempre con lo stesso sistema, mostra a video, un avvertimento per l'utente quando ad esempio, inserisce un dato non corretto, ma in questo caso non uso le eccezioni.
Grazie, ciao.
sottovento
24-11-2014, 20:49
public class GestisciEccezioni {
public GestisciEccezioni(Exception ex, Object obj){
switch (ex.getClass().getSimpleName()){
case "FileNotFoundException":
obj.getClass().getSimpleName() //ho il nome della JFrame o della classe che ha generato l'errore; volendo potrei passare anche il nome del metodo in errore.
break;
case "RuntimeException":
//faccio altre cose
case "SQLException":
//faccio altre cose
case "NullPointerException":
//faccio altre cose
default:
......
}
}
}
Le eccezioni possono essere generate da condizioni anomale nell'applicazione o nella VM.
Alcune condizioni anomale sono "fisiologiche": per esempio, tenti di aprire un file che ovviamente potrebbe non esistere. Ecco allora che la FileNotFoundException viene sollevata e giustamente deve essere gestita.
Altre condizioni sono dovute ad errori di programmazione, e gestirle potrebbe portarti a seri errori, magari da altre parti.
Un esempio e' proprio quello che hai scritto tu: NullPointerException, cosi' come molte altre sotto la RuntimeException.
Sei davvero sicuro che questa gestione ti porti a scrivere programmi SICURI e ROBUSTI? La NullPointerException, per esempio, nel 99% dei casi indica un errore di programmazione e non ha senso gestirlo, anzi, potrebbe diventare pericolosissimo.
Analogamente alla NullpointerException ce ne sono parecchie altre che estendono RuntimeException, e che gestirle ti porta a programmi instabili.
Le eccezioni figlie di RuntimeException vanno sempre valutate attentamente prima di decidere se farne il catch oppure no (che, ripetiamo, e' facoltativo): per esempio, non c'e' problema per la NumberFormatException, ma cosa fare in caso di ClassCastException? Non sarebbe davvero meglio segnalare l'errore e terminare, dando cosi' la possibilita' di correggere l'applicazione?
Sei davvero sicuro che questa gestione ti porti a scrivere programmi SICURI e ROBUSTI? La NullPointerException, per esempio, nel 99% dei casi indica un errore di programmazione e non ha senso gestirlo, anzi, potrebbe diventare pericolosissimo.
Analogamente alla NullpointerException ce ne sono parecchie altre che estendono RuntimeException, e che gestirle ti porta a programmi instabili.
Le eccezioni figlie di RuntimeException vanno sempre valutate attentamente prima di decidere se farne il catch oppure no (che, ripetiamo, e' facoltativo): per esempio, non c'e' problema per la NumberFormatException, ma cosa fare in caso di ClassCastException? Non sarebbe davvero meglio segnalare l'errore e terminare, dando cosi' la possibilita' di correggere l'applicazione?
sono perfettamente d'accordo, ma proprio in quei casi, magari nei loro case, potrei visualizzare un messaggio con l'uso di JOptionPane del tipo
"errore grave il programma verrà chiuso. contattare il fornitore e comunicare i seguenti dati...(metterò il nome della classe, il messaggio d'errore e il nome del metodo)" e un exit(n)
un programma che crasha da un momento all'altro segnalando l'errore classico di java senza comunicazione all'utente è davvero brutto.
pensa se programmi come access, photoshop facessero così.
infatti loro hanno un modulo con il pulsante "invia segnalazione errore" ....e poi crepano
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.