Voglio solo aggiungere qualche ragionamento per non usare affatto le eccezioni verificate. Questa non è una risposta completa, ma ritengo che risponda a una parte della tua domanda e integri molte altre risposte.
Ogni volta che sono coinvolte eccezioni controllate, c'è un punto throws CheckedException
nella firma di un metodo ( CheckedException
potrebbe esserci un'eccezione controllata). Una firma NON genera un'eccezione, generare eccezioni è un aspetto dell'implementazione. Interfacce, firme dei metodi, classi principali, tutte queste cose NON dovrebbero dipendere dalle loro implementazioni. L'uso delle eccezioni selezionate qui (in realtà il fatto che devi dichiarare ilthrows
firma del metodo) sta vincolando le interfacce di livello superiore con le implementazioni di tali interfacce.
Lascia che ti mostri un esempio.
Facciamo un'interfaccia bella e pulita come questa
public interface IFoo {
public void foo();
}
Ora possiamo scrivere molte implementazioni del metodo foo()
, come queste
public class Foo implements IFoo {
@Override
public void foo() {
System.out.println("I don't throw and exception");
}
}
Class Foo è perfettamente bene. Ora facciamo un primo tentativo in classe Bar
public class Bar implements IFoo {
@Override
public void foo() {
//I'm using InterruptedExcepton because you probably heard about it somewhere. It's a checked exception. Any checked exception will work the same.
throw new InterruptedException();
}
}
Questa barra di classe non verrà compilata. Poiché InterruptedException è un'eccezione verificata, è necessario acquisirla (con un metodo try-catch all'interno foo ()) o dichiarare che la si sta lanciando (aggiungendo throws InterruptedException
alla firma del metodo). Dato che non voglio catturare questa eccezione qui (voglio che si propaga verso l'alto in modo da poterla gestire correttamente da qualche altra parte), cambiamo la firma.
public class Bar implements IFoo {
@Override
public void foo() throws InterruptedException {
throw new InterruptedException();
}
}
Neanche questa barra di classe verrà compilata! Il metodo foo () di Bar NON sovrascrive il metodo foo () di IFoo poiché le loro firme sono diverse. Potrei rimuovere l'annotazione @Override, ma voglio programmare come l'interfaccia IFoo come IFoo foo;
e in seguito decidere su quale implementazione voglio usare, come foo = new Bar();
. Se il metodo foo di Bar () non sostituisce il metodo fooo di IFoo, quando lo facciofoo.foo();
non chiamerà l'implementazione di bar di foo ().
Per fare in modo che Bar public void foo() throws InterruptedException
sostituisca IFoo, DEVO public void foo()
aggiungere throws InterruptedException
la firma del metodo IFoo. Questo, tuttavia, causerà problemi con la mia classe Foo, poiché la sua firma del metodo foo () differisce dalla firma del metodo IFoo. Inoltre, se aggiungessi throws InterruptedException
al metodo foo () di Foo, otterrei un altro errore affermando che il metodo foo () di Foo dichiara che genera un InterruptedException ma non genera mai un InterruptedException.
Come puoi vedere (se ho fatto un lavoro decente nello spiegare queste cose), il fatto che sto lanciando un'eccezione controllata come InterruptedException mi sta costringendo a legare la mia interfaccia IFoo a una delle sue implementazioni, che a sua volta provoca il caos su IFoo altre implementazioni!
Questo è un grande motivo per cui le eccezioni controllate sono MALE. In maiuscolo.
Una soluzione è acquisire l'eccezione selezionata, racchiuderla in un'eccezione non selezionata e generare l'eccezione non selezionata.
DataSeries
classe che contiene dati che devono sempre rimanere in ordine temporale. C'è un metodo per aggiungere un nuovoDataPoint
alla fine di aDataSeries
. Se tutto il mio codice funziona correttamente in tutto il progetto,DataPoint
non si dovrebbe mai aggiungere un alla fine che ha una data precedente a quella già alla fine. Ogni modulo dell'intero progetto è costruito con questo principio. Tuttavia, controllo questa condizione e, se accade, genera un'eccezione non selezionata. Perché? Se succede, voglio sapere chi lo sta facendo e risolverlo.