Unterschied zwischen Throw und Throws in Java

1. Einleitung

In diesem Tutorial werfen wir einen Blick auf den Wurf und die Würfe in Java. Wir werden erklären, wann wir jeden von ihnen verwenden sollten.

Als nächstes zeigen wir einige Beispiele für ihre grundlegende Verwendung.

2. Werfen und werfen

Beginnen wir mit einer kurzen Einführung. Diese Schlüsselwörter beziehen sich auf die Ausnahmebehandlung. Ausnahmen werden ausgelöst, wenn der normale Ablauf unserer Anwendung unterbrochen wird.

Es kann viele Gründe geben. Ein Benutzer könnte die falschen Eingabedaten senden. Wir können eine Verbindung verlieren oder eine andere unerwartete Situation kann auftreten. Eine gute Behandlung von Ausnahmen ist ein Schlüssel, um unsere Anwendung nach dem Auftreten dieser unangenehmen Momente am Laufen zu halten.

Wir verwenden das Schlüsselwort throw, um explizit eine Ausnahme vom Code auszulösen. Es kann sich um eine beliebige Methode oder einen statischen Block handeln. Diese Ausnahme muss eine Unterklasse von Throwable sein. Es kann auch selbst ein Throwable sein. Wir können nicht mehrere Ausnahmen mit einem einzigen Wurf auslösen .

Das Schlüsselwort Throws kann in die Methodendeklaration eingefügt werden. Es gibt an, welche Ausnahmen von dieser Methode ausgelöst werden können. Wir müssen diese Ausnahmen mit try-catch behandeln.

Diese beiden Schlüsselwörter sind nicht austauschbar!

3. Java einwerfen

Schauen wir uns ein einfaches Beispiel an, bei dem eine Ausnahme von der Methode ausgelöst wird.

Stellen Sie sich zunächst vor, wir schreiben einen einfachen Taschenrechner. Eine der grundlegenden arithmetischen Operationen ist die Division. Aus diesem Grund wurden wir gebeten, diese Funktion zu implementieren:

public double divide(double a, double b) { return a / b; }

Da wir nicht durch Null teilen können, müssen wir einige Änderungen an unserem vorhandenen Code hinzufügen. Es scheint ein guter Moment zu sein, um eine Ausnahme auszulösen.

Lass uns das machen:

public double divide(double a, double b) { if (b == 0) { throw new ArithmeticException("Divider cannot be equal to zero!"); } return a / b; }

Wie Sie sehen können, haben wir ArithmeticException verwendet, die perfekt zu unseren Anforderungen passt. Wir können einen einzelnen String- Konstruktorparameter übergeben, der eine Ausnahmemeldung ist.

3.1. Gute Praktiken

Wir sollten immer die spezifischste Ausnahme bevorzugen. Wir müssen eine Klasse finden, die am besten zu unserer außergewöhnlichen Veranstaltung passt. Werfen Sie beispielsweise NumberFormatException anstelle von IllegalArgumentException. Wir sollten vermeiden, eine unspezifische Ausnahme zu werfen .

Zum Beispiel gibt es eine Integer- Klasse im Paket java.lang . Werfen wir einen Blick auf die Deklaration der Factory-Methode:

public static Integer valueOf(String s) throws NumberFormatException 

Es ist eine statische Factory-Methode, die eine Integer- Instanz aus String erstellt. Bei falscher Eingabe String wird das Verfahren werfen Number.

Eine gute Idee ist es, unsere eigene, aussagekräftigere Ausnahme zu definieren. In unserer Calculator- Klasse könnte dies beispielsweise DivideByZeroException sein.

Werfen wir einen Blick auf die Beispielimplementierung:

public class DivideByZeroException extends RuntimeException { public DivideByZeroException(String message) { super(message); } }

3.2. Umschließen einer vorhandenen Ausnahme

Manchmal möchten wir eine vorhandene Ausnahme in die von uns definierte Ausnahme einschließen.

Beginnen wir mit der Definition unserer eigenen Ausnahme:

public class DataAcessException extends RuntimeException { public DataAcessException(String message, Throwable cause) { super(message, cause); } }

Der Konstruktor akzeptiert zwei Parameter: eine Ausnahmemeldung und eine Ursache, die eine beliebige Unterklasse von Throwable sein kann.

Schreiben wir eine gefälschte Implementierung für die Funktion findAll () :

public List findAll() throws SQLException { throw new SQLException(); }

Rufen Sie nun in SimpleService eine Repository-Funktion auf, die zu SQLException führen kann:

public void wrappingException() { try { personRepository.findAll(); } catch (SQLException e) { throw new DataAccessException("SQL Exception", e); } }

Wir werfen SQLException erneut aus, die in unsere eigene Ausnahme namens DataAccessException eingeschlossen ist. Alles wird durch den folgenden Test überprüft:

@Test void whenSQLExceptionIsThrown_thenShouldBeRethrownWithWrappedException() { assertThrows(DataAccessException.class, () -> simpleService.wrappingException()); }

Dafür gibt es zwei Gründe. Zunächst verwenden wir Exception Wrapping, da der Rest des Codes nicht über jede mögliche Ausnahme im System Bescheid wissen muss.

Auch Komponenten höherer Ebenen müssen weder über Komponenten der unteren Ebene noch über die Ausnahmen, die sie auslösen, Bescheid wissen.

3.3. Multi-Catch mit Java

Manchmal können die von uns verwendeten Methoden viele verschiedene Ausnahmen auslösen.

Werfen wir einen Blick auf einen umfangreicheren Try-Catch-Block:

try { tryCatch.execute(); } catch (ConnectionException | SocketException ex) { System.out.println("IOException"); } catch (Exception ex) { System.out.println("General exception"); }

Die ausführen Methode kann drei Ausnahmen auslösen: Socket, Connection, Exception. Der erste catch-Block fängt ConnectionException oder SocketException ab . Der zweite catch-Block würde Exception oder eine andere Unterklasse von Exception abfangen . Denken Sie daran, dass wir immer zuerst eine detailliertere Ausnahme abfangen sollten.

Wir können die Reihenfolge unserer Fangblöcke tauschen. Dann würden wir niemals SocketException und ConnectionException abfangen, da mit Exception alles zum Fang geht .

4. Wirft Java ein

Wir fügen der Methodendeklaration Würfe hinzu .

Let's take a look at one of our previous method declaration:

public static void execute() throws SocketException, ConnectionException, Exception

The method may throw multiple exceptions. They are comma-separated at the end of a method declaration. We can put both, checked and unchecked exceptions in the throws. We have described the difference between them below.

4.1. Checked and Unchecked Exceptions

A checked exception means that it's checked at the compile time. Note, that we must handle this exception. Otherwise, a method must specify an exception by using throws keyword.

The most common checked exceptions are IOException, FileNotFoundException, ParseException. FileNotFoundException may be thrown when we create FileInputStream from File.

There's a short example:

File file = new File("not_existing_file.txt"); try { FileInputStream stream = new FileInputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); }

We can avoid using try-catch block by adding throws to the method declaration:

private static void uncheckedException() throws FileNotFoundException { File file = new File("not_existing_file.txt"); FileInputStream stream = new FileInputStream(file); }

Unfortunately, a higher level function still has to handle this exception. Otherwise, we have to put this exception in method declaration with throws keyword.

As the opposite, unchecked exceptions aren't checked at the compile time.

The most common unchecked exceptions are: ArrayIndexOutOfBoundsException, IllegalArgumentException, NullPointerException.

Unchecked exceptions are thrown during runtime. The following code will throw a NullPointerException. Probably it's one of the most common exceptions in Java.

Calling a method on a null reference will result in this exception:

public void runtimeNullPointerException() { String a = null; a.length(); }

Let's verify this behavior in the test:

@Test void whenCalled_thenNullPointerExceptionIsThrown() { assertThrows(NullPointerException.class, () -> simpleService.runtimeNullPointerException()); }

Bitte denken Sie daran, dass dieser Code und Test nicht viel Sinn macht. Es dient nur zu Lernzwecken, um Laufzeitausnahmen zu erklären.

In Java ist jede Unterklasse von Error und RuntimeException eine nicht aktivierte Ausnahme. Eine aktivierte Ausnahme ist alles andere unter der Throwable- Klasse.

5. Schlussfolgerung

In diesem Artikel haben wir den Unterschied zwischen zwei Java-Schlüsselwörtern erläutert: throw und throw . Wir haben die grundlegende Verwendung durchgearbeitet und ein wenig über bewährte Verfahren gesprochen . Dann haben wir über geprüfte und ungeprüfte Ausnahmen gesprochen.

Der Quellcode befindet sich wie immer auf unserem GitHub.

Wenn Sie sich eingehender mit der Ausnahmebehandlung in Java befassen möchten, lesen Sie bitte unseren Artikel über Java-Ausnahmen.