Ich möchte nur einige Gründe hinzufügen, warum geprüfte Ausnahmen überhaupt nicht verwendet werden. Dies ist keine vollständige Antwort, aber ich denke, sie beantwortet einen Teil Ihrer Frage und ergänzt viele andere Antworten.
Immer wenn geprüfte Ausnahmen betroffen sind, befindet sich throws CheckedException
irgendwo in einer Methodensignatur eine ( CheckedException
möglicherweise jede geprüfte Ausnahme). Eine Signatur löst KEINE Ausnahme aus. Das Auslösen von Ausnahmen ist ein Aspekt der Implementierung. Schnittstellen, Methodensignaturen, übergeordnete Klassen, all diese Dinge sollten NICHT von ihren Implementierungen abhängen. Die Verwendung von aktivierten Ausnahmen hier (tatsächlich die Tatsache, dass Sie die throws
in der Methodensignatur deklarieren müssen) bindet Ihre übergeordneten Schnittstellen an Ihre Implementierungen dieser Schnittstellen.
Lassen Sie mich Ihnen ein Beispiel zeigen.
Lassen Sie uns eine schöne und saubere Oberfläche wie diese haben
public interface IFoo {
public void foo();
}
Jetzt können wir viele Implementierungen von Methoden foo()
wie diese schreiben
public class Foo implements IFoo {
@Override
public void foo() {
System.out.println("I don't throw and exception");
}
}
Class Foo ist vollkommen in Ordnung. Machen wir jetzt einen ersten Versuch in der Klasse 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();
}
}
Diese Klassenleiste wird nicht kompiliert. Da InterruptedException eine aktivierte Ausnahme ist, müssen Sie sie entweder erfassen (mit einem Try-Catch innerhalb der Methode foo ()) oder deklarieren, dass Sie sie auslösen ( throws InterruptedException
zur Methodensignatur hinzufügen ). Da ich diese Ausnahme hier nicht erfassen möchte (ich möchte, dass sie sich nach oben ausbreitet, damit ich sie an anderer Stelle richtig verarbeiten kann), ändern wir die Signatur.
public class Bar implements IFoo {
@Override
public void foo() throws InterruptedException {
throw new InterruptedException();
}
}
Diese Klassenleiste wird auch nicht kompiliert! Die Methode foo () von Bar überschreibt NICHT die Methode foo () von IFoo, da ihre Signaturen unterschiedlich sind. Ich könnte die @ Override-Annotation entfernen, aber ich möchte gegen die Schnittstelle IFoo wie programmieren IFoo foo;
und später entscheiden, welche Implementierung ich verwenden möchte, wie foo = new Bar();
. Wenn die Methode foo () von Bar die Methode foo von IFoo nicht überschreibt, wenn ich das tuefoo.foo();
wird die Implementierung von foo () von Bar nicht aufgerufen.
Damit Bar public void foo() throws InterruptedException
IFoos überschreibt, public void foo()
MUSS throws InterruptedException
ich die Methodensignatur von IFoo ergänzen . Dies führt jedoch zu Problemen mit meiner Foo-Klasse, da sich die Signatur der foo () -Methode von der Signatur der IFoo-Methode unterscheidet. Wenn ich außerdem throws InterruptedException
zu Foos Methode foo () hinzufügen würde, würde ich einen weiteren Fehler erhalten, der besagt, dass Foos Methode foo () deklariert, dass sie eine InterruptedException auslöst, aber niemals eine InterruptedException auslöst.
Wie Sie sehen können (wenn ich gute Arbeit geleistet habe, um dieses Zeug zu erklären), zwingt mich die Tatsache, dass ich eine aktivierte Ausnahme wie InterruptedException auslöse, dazu, meine Schnittstelle IFoo an eine ihrer Implementierungen zu binden, was wiederum Chaos bei IFoo verursacht andere Implementierungen!
Dies ist ein wichtiger Grund, warum geprüfte Ausnahmen SCHLECHT sind. In Kappen.
Eine Lösung besteht darin, die aktivierte Ausnahme zu erfassen, sie in eine nicht aktivierte Ausnahme zu verpacken und die nicht aktivierte Ausnahme auszulösen.
DataSeries
Klasse, die Daten enthält, die immer in zeitbasierter Reihenfolge bleiben müssen. Es gibt eine Methode, umDataPoint
am Ende von a eine neue hinzuzufügenDataSeries
. Wenn mein gesamter Code während des gesamten Projekts ordnungsgemäß funktioniert,DataPoint
sollte am Ende niemals ein Code hinzugefügt werden, der ein vorheriges Datum zu dem bereits am Ende hat. Jedes Modul im gesamten Projekt wird mit dieser Binsenweisheit erstellt. Ich überprüfe diese Bedingung jedoch und löse eine ungeprüfte Ausnahme, wenn dies passiert. Warum? Wenn es passiert, möchte ich wissen, wer dies tut und es beheben.