2012-06-13 15 views
17

Ho sentito dire che prendere lo java.lang.Error è considerato una cattiva pratica. Attualmente sto caricando un dll che non è garantito sul PATH e vorrei passare a un percorso configurato dall'utente nel caso in cui non lo fosse.Errori Java durante la cattura

try { 
    System.loadLibrary("HelloWorld"); 
} catch(UnsatisfiedLinkError ule){ 
    System.load("C:/libraries/HelloWorld.dll"); 
} 

C'è un modo migliore per farlo? O sta prendendo il UnsatisfiedLinkError qui accettabile?

+5

Nessuna idea sulla convetion corretta qui, ma è possibile verificare se il file esiste prima di provare ... ['new File (" path/helloworld.dll ") .exists()'] (http: // docs. oracle.com/javase/7/docs/api/java/io/File.html#exists%28%29) .... (modifica: suggerimento errato, ho interpretato erroneamente il codice) –

+5

Lo considererei una soluzione accettabile. –

+0

@Slanec Dovresti cercare tutte le directory nel 'java.library.path' –

risposta

16

Oltre a dare consigli su come risolvere tecnicamente il problema, vorrei prendere un momento e spiegare perché è considerato "cattiva pratica" in primo luogo.

Iniziamo chiarendo cosa è la classe Error.


In java vengono generati errori ed eccezioni (che sono i tipi principali). Lanciare uno dei precedenti è fatto usando la parola chiave throw. Ogni classe che estende il numero di base java.lang.Throwable può essere lanciata.

Esistono due classi che ereditano dalla classe base Throwable: Exception e Error. La differenza tra i due è spiegata nei loro documentazioni:

Un errore è una sottoclasse di Throwable che indica gravi problemi che un'applicazione ragionevole non dovrebbe cercare di catturare. La maggior parte degli errori sono condizioni anormali. [...]

Source

La classe Exception e le sue sottoclassi sono una forma di Throwable che indica le condizioni che un ragionevole applicazione potrebbe desiderare per la cattura .

Source


Come spiegato in precedenza, gli errori ed eccezioni sono separati a causa delle loro diverse origini. Un Error indica normalmente un problema, che l'applicazione non è in grado di ripristinare da. Pertanto, non dovrebbero essere catturati.

Lo stesso vale per RuntimeException, ma viene utilizzato per indicare un problema con un livello di livello alto (ad esempio metodi). Mentre lo Error indica un problema di basso livello (ad es. Il runtime).


Così, ora che avete capito che si deve solo intercettare le eccezioni e gli errori che si è in grado di recuperare da, la risposta alla tua domanda dovrebbe essere chiaro.

Sì, è perfettamente ragionevole prendere lo UnsatisfiedLinkError perché l'applicazione può ripristinarlo.


ho coperto sopra (in modo più dettagliato e con esempi) ed alcune informazioni estese in article on my Blog.

+0

Una volta ho dovuto violare questo paradigma è stato quando ho dovuto lanciare un errore normale attraverso una classe che stavo derivando da che non ha specificato alcuna eccezione. Quindi ho ricavato da 'RuntimeException' per aggirare i requisiti linguistici. Vorrei ancora che ci fosse un modo migliore per farlo. – djechlin

+0

Se l'applicazione non riesce a risollevarsi da un errore, non stai peggio afferrandolo, vero? – simon

+0

@simon se davvero non riesci a recuperare dall'errore, cosa hai intenzione di fare quando lo prendi? Se l'applicazione non funziona più, perché tenerla in esecuzione? –

0

loadLibrary chiama findLibrary() che sarebbe utile ma è protetto, la soluzione migliore è scrivere la propria classe estendendo ClassLoader. Il programma di caricamento classi ha un metodo protetto chiamato findLibrary() che restituisce il percorso di una libreria o null se non esiste. In questo modo è possibile verificare la presenza di null invece di rilevare errori. Non sono sicuro che questo sia effettivamente "migliore", ma eliminerà il tuo bisogno di provare a catturare;

+0

La libreria potrebbe essere eliminata dopo il controllo e prima del caricamento, quindi è ancora necessario il tentativo di intercettazione. –

0

Se si sta codificando in modo difensivo e si può ripristinare da un problema, allora non è un Java Error. Se un problema del genere non è molto probabile, quindi creare una sottoclasse di Exception e lanciarlo e catturarlo. Se un tale problema è probabile, allora non dovrebbe nemmeno lanciare un Exception; ma, dovrebbe essere parte del flusso regolare del codice.

try { 
    if (config.hasCustomDLL()) { 
    System.load(config.getCustomDLL()); 
    } else { 
    System.loadLibrary(Config.DEFAULT_DLL); 
    } 
} catch (UnstatisfiedLinkError e) { 
    System.out.println("Error loading DLL: " + e); 
} 

Errors sono pensati per gli errori davvero male, non recuperabili "fallimenti", che in realtà non sono nemmeno gli errori se non v'è una soluzione adatta. Non sovraccaricare il sistema progettato per gestire i guasti con ciò che equivale a una capacità di configurare il sistema in più modi.

0

È necessario rilevare gli errori solo in casi molto specifici. Solo catture e errori se hai esplorato tutte le altre possibilità. Sono completamente d'accordo con tutto ciò che Lukas Knuth ha detto. Ma ho una piccola aggiunta. Nel caso in cui si rilevino errori di qualsiasi tipo, assicurarsi di rilevare gli errori da un ambito il più ristretto possibile. Inoltre, se possibile, assicurati che i metodi su cui trovi errori siano dichiarati come definitivi. Il motivo è che gli errori di cattura di solito possono portare a programmi molto instabili. Si consideri che si rileva un errore su un metodo che in seguito è stato esteso per chiamare altri metodi, ora tutti questi metodi sottostanti hanno anche errori (involontariamente) catturati dal fermo sovrastante.

Se è necessario rilevare un errore, farlo in una fasion stretta e controllata.

Problemi correlati