2015-01-28 10 views
7

Sto usando SonarQube per la qualità del codice. Ho ricevuto un problema relativo alla gestione delle eccezioni, che dice rimuovere la clausola throw dal blocco finally.Come evitare la clausola throw in finally block

} catch(Exception e) { 
      throw new MyException("request failed : ", e); 
     } finally { 
      try { 
       httpClient.close(); 
      } catch (IOException e) {    
       throw new MyException("failed to close server conn: ", e); 
      } 
     } 

Sulla base delle mie conoscenze sopra il codice sembra buono. Se rimuovo la clausola throw e sopprimo l'eccezione, finalmente il chiamante di questo metodo non sarà in grado di conoscere lo stato del server. Non sono sicuro di come possiamo ottenere la stessa funzionalità senza avere una clausola di lancio.

+0

Forse si tenta di aggiungere un blocco 'finally' in quella interna blocco' try-catch' e vedere se avverte ancora? – Vikdor

+0

Se si stanno già utilizzando clausole di lancio per indicare altri errori nella stessa funzione, forse sarebbe imprudente utilizzare un metodo diverso per questo caso particolare? – Troyseph

+0

Oh, penso che tu sia preoccupato perché anche se la connessione non viene mai eseguita correttamente, il tuo blocco 'finally' getta ancora il tuo' MyException', vero? – Troyseph

risposta

5

Il tuo colpo migliore è quello di utilizzare la funzione Automatic Resource Management di Java, disponibile dal momento che Java 7. Se è per qualche motivo non è disponibile per voi, allora la cosa migliore da fare è quello di replicare quello che lo zucchero sintattico si espande in:

public static void runWithoutMasking() throws MyException { 
    AutoClose autoClose = new AutoClose(); 
    MyException myException = null; 
    try { 
     autoClose.work(); 
    } catch (MyException e) { 
     myException = e; 
     throw e; 
    } finally { 
     if (myException != null) { 
      try { 
       autoClose.close(); 
      } catch (Throwable t) { 
       myException.addSuppressed(t); 
      } 
     } else { 
      autoClose.close(); 
     } 
    } 
} 

cose da notare:

  • il codice inghiotte l'eccezione originale dal blocco try nel caso in cui la chiusura della risorsa non riesce. L'eccezione originale è sicuramente più importante per la diagnostica;
  • nel linguaggio ARM precedente, la chiusura della risorsa viene eseguita in modo diverso a seconda che esistesse già un'eccezione nel blocco try. Se try viene completato normalmente, la risorsa viene chiusa all'esterno di qualsiasi blocco try-catch, propagando naturalmente qualsiasi eccezione.
2

In genere, i metodi nel blocco finally sono codici 'cleanup' (Chiusura di Connection, ecc.) Che l'utente non deve necessariamente conoscere.

Quello che faccio per queste eccezioni è quella di assorbire l'eccezione, ma registro i dettagli.

finally{ 
    try{ 
     connection.close(); 
    }catch(SQLException e){ 
     // do nothing and just log the error 
     LOG.error("Something happened while closing connection. Cause: " + e.getMessage()); 
    } 
} 
0

io non sono sicuro di come possiamo raggiungere stessa funzionalità senza dover clausola di tiro.

Si potrebbe nido i due try blocchi in modo diverso per ottenere lo stesso risultato:

HttpClient httpClient = null; // initialize 
try { 
    try { 
     // do something with httpClient 
    } catch(Exception e) { 
     throw new MyException("request failed : ", e); 
    } finally { 
     httpClient.close(); 
    } 
} catch (IOException e) {    
    throw new MyException("failed to close server conn: ", e); 
} 
1

che stai ricevendo un avvertimento, perché questo codice potrebbe potenzialmente generare un'eccezione mentre si occupano di un eccezione generata. È possibile utilizzare la sintassi con la risorsa per chiudere automaticamente la risorsa. Read more here.

Nel caso in cui la "richiesta non riuscita:" viene generata un'eccezione e non si riesce a chiudere il HttpClient, la seconda eccezione è quella che avrebbe bolla.

Problemi correlati