Die 11 besten Best Practices für Java-Ausnahmen

In meinem vorherigen Tutorial zu Java-Ausnahmen habe ich unterdrückte Ausnahmen und die Java-Ausnahmebehandlung behandelt. Es ist eine der wichtigsten Codierungspraktiken, eine effiziente und narrensichere Ausnahmebehandlung für Ihre Projekte durchzuführen. Um dies zu erreichen, müssen Sie über gute Kenntnisse der Best Practices für Ausnahmen verfügen. In diesem Tutorial werden die wichtigsten Best Practices hervorgehoben, die von Java-Programmierern verwendet werden, um die Qualität der Ausnahmebehandlung zu verbessern. Wenn Sie Fragen haben, schreiben Sie diese bitte in den Kommentarbereich.

Best Practices für Java-Ausnahmen

1. Unterdrücken/verschlucken Sie die Ausnahme im Catch-Block nicht

public class ExceptionExample {
	public FileInputStream testMethod1(){
		File file = new File("test.txt");
		FileInputStream fileInputStream = null;
		try{
			fileInputStream = new FileInputStream(file);
			fileInputStream.read();
		}catch (IOException e){			
			return null;
		}
		return fileInputStream;
	}
	public static void main(String[] args){
		ExceptionExample instance1 = new ExceptionExample();
		instance1.testMethod1();
	}
}

Das Verschlucken der Ausnahme ist eine der schlechten Praktiken bei der Ausnahmebehandlung. Im obigen Beispiel wird jede ausgelöste Ausnahme vollständig ignoriert und es gibt keinen Hinweis darauf, wo das Problem liegt. Es empfiehlt sich immer, die Ausnahme auf die äußere Ebene zurückzuwerfen oder die Ausnahme zu behandeln und eine alternative Lösung durchzuführen.

public class ExceptionExample {
	public FileInputStream testMethod1() throws IOException{
		File file = new File("test.txt");
		FileInputStream fileInputStream = null;
		try{
			fileInputStream = new FileInputStream(file);
			fileInputStream.read();
		}catch (IOException e){			
			throw e;
		}
		return fileInputStream;
	}
	public static void main(String[] args) throws IOException{
		ExceptionExample instance1 = new ExceptionExample();
		instance1.testMethod1();
	}
}

2. Deklarieren Sie eine bestimmte Ausnahme in der throws-Klausel des Methodenblocks

Das Schreiben wie die folgende throws-Klausel macht den gesamten Zweck der geprüften Ausnahmen zunichte:

public FileInputStream testMethod1() throws Exception{

Dies ist keine gute Vorgehensweise. Wir müssen immer versuchen, die spezifischste Ausnahmeklasse zu verwenden, die vom Programm ausgelöst wird. Die am besten passende throws Klausel wäre:

public FileInputStream testMethod1() throws IOException{

3. Fangen Sie bestimmte Ausnahmeklassen ab

Es ist immer eine gute Idee, die spezifischen Klassen abzufangen, die von der Anwendung ausgelöst werden. Wenn von der Anwendung mehrere Ausnahmen ausgelöst werden, die demselben Typ angehören, ist es keine gute Idee, nur die Superklasse abzufangen.

Zum Beispiel, wenn Ihr Code beides auslöst FileNotFoundException Und IOExceptionhaben Sie zwei Catch-Klauseln für beide Ausnahmen in der Hierarchie, anstatt eine Catch-Klausel mit zu schreiben IOException oder im schlimmsten Fall einfach eine Catch-Klausel schreiben Exception.

Hier ist der richtige Weg, um die spezifische Ausnahmeklasse abzufangen:

try {
   //some statements
catch(FileNotFoundException e){
//handle here
}
catch(IOException e){
//handle here
} 

Sie sollten die Ausnahme niemals wie folgt abfangen:

try {
   //some statements
catch(Exception e){
//handle here
}

4. Geben Sie die Ressourcen im Final-Block frei

Wenn Sie eine Datenbankverbindung öffnen, werden Dateivorgänge oder andere ressourcenbezogene Vorgänge ordnungsgemäß geschlossen, andernfalls führt dies zu einem Leistungsproblem für Ihre Anwendung. Wenn Sie beispielsweise eine Datenbankverbindung geöffnet und CRUD-Vorgänge ausgeführt haben, wird die Verbindung durch alle ausgelösten Ausnahmen für immer geöffnet und niemals geschlossen.

Um das schlimmste Szenario zu vermeiden, empfiehlt es sich immer, die geöffneten Ressourcen im „finally“-Block zu schließen. Hier ist ein Beispielcode zum Schließen der Datenbankverbindungen im „finally“-Block:

finally {
        try {
            if (con != null) {
                con.close();
            }
            if (stat != null) {
                stat.close();
            }
        } catch (SQLException sqlee) {
            sqlee.printStackTrace();
        }
    }

Wenn Sie das nächste Mal feststellen, dass Ihr Teammitglied den „finally“-Block nicht zum Schließen der Ressourcen verwendet, kneifen Sie es, damit es der Best Practice folgt :).

5. Ausnahmen wirken sich auf die Leistung aus

Leistung von Java-Ausnahmen

Ausnahmen sind sehr, sehr teuer. Diese Aussage sollte sich jeder Java-Programmierer beim Schreiben des Codes merken. Das Erstellen einer Ausnahme ist ein sehr langsamer Vorgang und das Auslösen einer Ausnahme kostet etwa 1–5 Mikrosekunden. Wenn die Ausnahmen auf mehrere Ebenen verteilt werden, wird die gesamte Anwendung verlangsamt.

  • Nutzen Sie die Ausnahmen in den Ausnahmebedingungen
  • Verwenden Sie die Ausnahmen, wenn es wiederherstellbar ist

Obwohl die Verwendung von Ausnahmen sinnvoll ist, sollten Sie besser vermeiden, zu viele Stack-Traces in Ihrem Programm zu erfassen. In vielen Fällen sind sie nicht einmal notwendig, um das Problem zu verstehen – insbesondere, wenn sie ein Problem abdecken, das Sie bereits erwarten. Die Ausnahmemeldung könnte sich daher als ausreichende Information erweisen.

6. Verwenden Sie Standardausnahmen

Schreiben Sie keine benutzerdefinierten Ausnahmen, wenn das Problem mit den integrierten Ausnahmen behoben werden kann. Die Java-API selbst bietet Hunderte von Ausnahmen für verschiedene Bedingungen. Versuchen Sie zunächst, dieselben Ausnahmen für Ihre Anwendung zu verwenden. Wenn dies nicht ausreicht und Ihrem Geschäftsszenario keinen Sinn ergibt, erstellen Sie Ihre eigenen benutzerdefinierten Ausnahmen.

Wenn Sie die integrierten Ausnahmen verwenden, kann auch jeder neue Entwickler oder Außenstehende den Code verstehen. Sie müssen Ihren Code nicht mit Ihrer eigenen API sperren.

7. Wickeln Sie die Ausnahmen korrekt ein

Wenn Sie Ihre Anwendungen erneut auslösen, ist es wichtig, die ursprünglichen Ausnahmen ordnungsgemäß zu verpacken, da sonst der Ursprung der Ausnahmen verloren geht. Schau dir das Beispiel an:

import java.io.IOException;
public class HelloWorld{
     public static void main(String []args) throws Exception{
        try{
            throw new IOException("IOException");    
        }catch (IOException e){
            throw new ExampleException1("Example Exception and " + e.getMessage());
        }
        
     }
}
class ExampleException1 extends Exception{
    public ExampleException1(String s, Throwable t){
        super(s,t);
    }
    public ExampleException1(String s){
        super(s);
    }
}

Die Ausgabe für das obige Programm sieht wie folgt aus:

Exception in thread "main" ExampleException1: Example Exception and IOException                                                                                          
        at HelloWorld.main(HelloWorld.java:8)                   

In der obigen Ausgabe geht der IOException-Stack-Trace verloren, weil wir nicht den richtigen Konstruktor zum Umschließen der Ausnahmen verwendet haben. Ändern Sie den Catch-Block wie folgt, um die Ausnahmen richtig einzuschließen:

catch (IOException e){
            throw new ExampleException1("Example Exception",e);
        }

Die Ausgabe wird sein:

Exception in thread "main" ExampleException1: Example Exception                                                                                                
        at HelloWorld.main(HelloWorld.java:8)                                                                                                                            
Caused by: java.io.IOException: IOException                                                                                                                              
        at HelloWorld.main(HelloWorld.java:6)          

8. Vermeiden Sie es, eine Ausnahme aus dem „finally“-Block auszulösen

try {
  method();  //here throws first exception
} finally {
  shutdown(); //If finally blockthrew any exception the first exception will be lost forever
}

Beachten Sie im obigen Beispielausschnitt, dass die Möglichkeit besteht, dass „finally block“ auch eine Ausnahme auslöst. Wenn eine Ausnahme ausgelöst wird, geht die erste Ausnahme verloren, falls beide Ausnahmen gleichzeitig ausgelöst werden. Es empfiehlt sich, die Ausnahme zu behandeln, indem die Fehlermeldungen endgültig blockiert oder protokolliert werden. Es wurde jedoch nie eine Ausnahme vom „finally“-Block ausgelöst.

9. Verwenden Sie keine Ausnahmen zur Flusskontrolle

Sie sollten niemals Ausnahmen verwenden, um den Ablauf Ihres Programms zu steuern. Anstatt beispielsweise die if-Bedingung zu verwenden, ist die Verwendung einer Ausnahme zur Validierung eines Szenarios eine der schlimmsten Vorgehensweisen, die sich auf die Leistung Ihrer Anwendung auswirkt.

10. Fangen Sie nicht die Throwable-Klasse

Sie sollten in Ihrem Programm niemals die Throwable-Klasse verwenden. Fehler sind ebenfalls eine Unterklasse der Throwable-Klasse. Die Fehler können nicht einmal von der JVM selbst behoben werden.

11. Dokumentieren Sie die Ausnahmen

Machen Sie es sich zur Gewohnheit, alle Ausnahmen in Ihrer Bewerbung zu dokumentieren. Wenn Sie in Ihrer Anwendung eine benutzerdefinierte Ausnahme schreiben, kennt niemand auf der Welt außer Ihnen die Ursache für diese Ausnahme :). Sie müssen Ihrem Team also einen Gefallen tun, indem Sie eine gute Erklärung über die Ursache dieser Ausnahme und den Umgang damit verfassen. Vertrauen Sie mir, das wird bei Bedarf eine große Hilfe sein.

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Nach oben scrollen