[Inhouse-Studiensitzung] Behandlung von Java-Ausnahmen (26.04.2017)

0. Einleitung


Zielperson


Was ich erzählen möchte

Erläutern Sie die Regeln für Ausnahmen aus Sicht von API-Erstellern und API-Benutzern. API (Application Program Interface) setzt eine öffentliche Methode voraus.


Nachschlagewerke

Effektive Java 2nd Edition

参考図書.jpg

Ein Buch aus der Java 6-Ära, ein bisschen alt, aber ein gutes Buch. Die Regeln sind mit einem Schwerpunkt auf Klarheit und Prägnanz geschrieben.


Inhaltsverzeichnis

  1. Zusammenfassung der Ausnahmen
  2. Ausnahmeregeln für API-Benutzer
  3. Ausnahmeregeln für API-Autoren
  4. Anhang

1. Zusammenfassung der Ausnahmen


Was sind Ausnahmen?

Die Ausnahmeverarbeitung (reigaishori) dient dazu, die aktuelle Verarbeitung zu unterbrechen (zu stoppen) und eine weitere Verarbeitung durchzuführen, wenn eine Anomalie auftritt, während das Programm eine bestimmte Verarbeitung ausführt. Die zu diesem Zeitpunkt auftretende Abnormalität wird als Ausnahme bezeichnet.

Behandlung von Wikipedia-Ausnahmen Zitat


Überprüfte Ausnahmen und Laufzeitausnahmen

Ausnahmetypstruktur


java.lang.Exception
 -  IOException
 -  SQLException
 -  RuntimeException
     - NullPointerException
     - IllegalArgumentException

Syntax für die Ausnahmebehandlung (Aufrufmethode zum Auslösen)

Bei Verwendung des Konstruktors von java.io.FileReader.

throw definiert die Ausnahme, die die Methode auslöst.

public FileReader(File file) throws FileNotFoundException

Was tun, wenn eine Methode aufgerufen wird, die eine Ausnahme auslöst?

try {
  FileReader fr = new FileReader(file);  
} catch(FileNotFoundException e) {
  //...
}
private void read(File file) throws FileNotFoundException {
    FileReader fr = new FileReader(file);  
}

Syntax für die Ausnahmebehandlung (löst explizit eine Ausnahme aus)

Verwenden Sie das reservierte Wort "werfen".

private void read(File file) {
  if (file == null) {
     throw new NullPointerException("file is null");
  }
}

Überprüfte Ausnahmen müssen "Würfe" in der Methode deklarieren. Es sind keine Laufzeitausnahmen (wie NullPointerException) erforderlich. Eine Beschreibung der geprüften Ausnahmen und Laufzeitausnahmen wird später gegeben.


Syntax für die Ausnahmebehandlung (Multi-Catch)

Verfügbar ab Java 7.

Für Java 6 oder früher

catch (IOException ex) {
     logger.log(ex);
     throw ex;
} catch (SQLException ex) {
     logger.log(ex);
     throw ex;
}

Für Java 7 oder höher

catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}

https://docs.oracle.com/javase/jp/8/docs/technotes/guides/language/catch-multiple.html Referenz


2. Ausnahmeregeln für API-Benutzer


Ausnahmen nicht ignorieren (Punkt 65)

Ignorieren ist das Schlimmste. Definitiv nein.

try {
   ...
} catch(SomeException e) {}

Ein leerer catch-Block erfüllt nicht den Zweck der Ausnahme. Ihr Zweck ist es, "den Umgang mit außergewöhnlichen Bedingungen zu erzwingen".

Persönliche Ansicht


Verwenden Sie Ausnahmen nur für außergewöhnliche Bedingungen (Punkt 57).

Was ist los? Eine Ausnahme wird verwendet, um das Ende der Schleife zu bestimmen.

int[] array = {1,2,3,4,5};
try {
	int i=0;
	while(true) {
		System.out.println(array[i++]);
        //Andere Verarbeitung
	}
} catch(ArrayIndexOutOfBoundsException e) {}

Ausnahmen sollten, wie der Name schon sagt, nur für außergewöhnliche Bedingungen verwendet werden. Es sollte niemals für normale Kontrollflüsse verwendet werden.


[Persönliche Ansicht] Fang mit entsprechenden Ausnahmen

Ich kann es mit "IOException" abfangen, aber ich fange es mit "java.lang.Exception" ab.

File file = new File("/tmp/sample.txt");
try {
  FileReader fr = new FileReader(file);  
} catch(Exception e) { //IOException ist angemessen
  //...
}

Problem


Wenn Sie es mit java.lang.Exception fangen können

Framework-Verarbeitung etc. Wenn Sie die Weitergabe von Ausnahmen nicht irgendwo stoppen, fällt Ihr System (z. B. Tomcat) aus.

In der folgenden Quelle wird die Geschäftslogik im Rahmen von Terasoluna aufgerufen.

java:jp.terasoluna.fw.ex.aop.log.BLogicLogInterceptor.java


 public Object invoke(MethodInvocation invocation) throws Throwable {
       //...
        try {
           //Geschäftslogik ausführen
            result = invocation.proceed();
        } catch (Throwable e) {
            if (checkException(e)) {
                logger.error(e); //[Ausnahmeausgabe]
                throw e;
            } else {
                logger.debug(e); //[Ausnahmeausgabe]
                throw e;
            }
        }
}        

[Persönliche Ansicht] Der Bereich der Versuchsblöcke ist nicht zu groß

Eine Verarbeitung, die keine Ausnahme auslöst, sollte nach Möglichkeit nicht im try-Block beschrieben werden.

try {
  //Andere Verarbeitung als Dateien(Ausnahme wird nicht geworfen)
  initialize();
  //Dateibezogene Verarbeitung
  File file = new File("/tmp/sample.txt");
  FileReader fr = new FileReader(file);  
} catch(IOException e) { 
  //...
}

Problem


3. Ausnahmeregeln für API-Autoren


Verwenden Sie Laufzeitausnahmen für Programmierfehler (Punkt 58).

Die meisten Laufzeitausnahmen weisen auf Verstöße gegen die Vorbedingungen hin. Ein Verstoß gegen die Vorbedingung besteht darin, dass der API-Client den in der API-Spezifikation definierten Vertrag einfach nicht einhält.

Häufig gesehene Laufzeitausnahmen

http://qiita.com/yuba/items/d41290eca726559cd743 Referenz

Ausnahmen, die API-Benutzer vermeiden können, API-Benutzerverantwortlichkeiten.


Verwenden Sie geprüfte Ausnahmen (geprüfte Ausnahmen) für wiederherstellbare Zustände (Punkt 58).

Verwenden Sie keine aktivierten Ausnahmen für Situationen, in denen der Anrufer ordnungsgemäß wiederherstellen kann.

Ich bin mir nicht sicher über den "wiederherstellbaren Zustand".

Laut http://qiita.com/yuba/items/d41290eca726559cd743 "ist die überprüfte Ausnahme ein abnormales System, für das der Anrufer nicht verantwortlich ist."

Häufig gesehene Inspektionsausnahmen

Da dies nicht vermieden werden kann, muss der API-Benutzer "über das abnormale System nachdenken".


Ist IOException überhaupt unvermeidlich?

Wenn Sie einen Dateipfad übergeben, der im FileReader-Konstruktor nicht vorhanden ist, tritt eine FileNotFoundException auf. Selbst wenn das Vorhandensein der Datei bestätigt wird, kann die Datei unmittelbar danach gelöscht werden, sodass sie nicht vollständig vermieden werden kann.

File file = new File("/tmp/sample.txt");
if (file.exists() ){ 
  //Wenn die Datei hier gelöscht wird, tritt in der nächsten Zeile eine Ausnahme auf
  FileReader fr = new FileReader(file);
}  

Meine Sicht

Wenn "es nicht in der Verantwortung des API-Benutzers liegt", scheint es nicht "die Verantwortung des API-Erstellers" zu sein. Vielleicht kann niemand Verantwortung übernehmen.

Der API-Ersteller hatte das Gefühl, dass er eine Prüfausnahme mit der Bedeutung auslöste, dass "selbst wenn ein abnormales System auftritt, dies nicht in meiner Verantwortung liegt".


Gibt es eine Prüfausnahme auch in der Verantwortung des API-Benutzers?

Die Methode java.text.DateFormat # parse löst eine aktivierte Ausnahme ParseException aus.

ParseException - Wenn der Anfang der angegebenen Zeichenfolge nicht analysiert werden kann.

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
try {
	sdf.parse("abc"); //PrseException werfen
} catch (ParseException e) {
	e.printStackTrace();
}

Integer.parseInt löst eine Laufzeitausnahme NumberFormatException aus. SimpleDateFormat ist nicht threadsicher und kann eine aktivierte Ausnahme auslösen.


[Persönliche Meinung] Wirf nicht java.lang.Exception

/**Datei lesen*/
List<String> read(File file) throws Exception {
  List<String> lines = new ArrayList<>();
  FileReader fr = new FileReader(file);
  //....
  return lines;
}  

Problem


4. Anhang


C-Sprache, für die es keinen Ausnahmebehandlungsmechanismus gibt

Der Fehler wird durch einen Rückgabewert oder ein Ausgabeargument dargestellt.


/**
 * 0:Erfolg
 * -1:Argument Fehler
 * -2:Dateibezogene Fehler
 * /
int read(char *file) {
  //...
}

int sub(char *file) {
  int rtn = read(file);
  return rtn;
}

int main() {
  int rtn = sub(file);
}

Problem


Vor- und Nachteile von Inspektionsausnahmen

Nur Java implementiert geprüfte Ausnahmen in wichtigen Sprachen. Jede Inspektionsausnahme ist negativ.

http://qiita.com/Kokudori/items/0fe9181d8eec8d933c98


endlich Klausel und zurück

Wenn bei der Rückkehr in der try-catch-finally-Klausel die finally-Klausel festgelegt ist, wird das Innere der finally-Klausel immer vor der Rückkehr ausgeführt.

source-try.java


public class Try {
    public static void main(String[] args) {
        String i=TryCatch();
        System.out.println(i);
    }

    public static String TryCatch(){
        System.out.println("Start!");
        String str = null;//Mach es null
        try{
            str.toString();     //NullPointerException
            System.out.println("Hogehoge");
            return "Die Rückkehr von der Try-Klausel.";
        }catch(Exception e){
            System.out.println("Fuga Fuga");
            return "Die Rückkehr von der Catch-Klausel.";
        }finally{
            System.out.println("Die finally-Klausel wurde ausgeführt.");
        }
    }
}

System.out


Start!
Fuga Fuga
Die finally-Klausel wurde ausgeführt.
Die Rückkehr von der Catch-Klausel.

Zitiert von http://qiita.com/eijenson/items/7e9e112e69b37f72353c


Break, continue, return, System.exit sind in der finally-Klausel verboten

Diese unterliegen beim Kompilieren mit javac keinen Fehlern oder Warnungen. Wenn ich jedoch Eclipse verwende, erhalte ich eine Warnung bezüglich break, continue und return, dass "finally block nicht erfolgreich abgeschlossen werden kann".

Zitiert von http://www.atmarkit.co.jp/ait/articles/0611/22/news145.html

public class Try {
    public static void main(String[] args) {
        String i=TryCatch();
        System.out.println(i);
    }

    public static String TryCatch(){
        System.out.println("Start!");
        String str = null;//Mach es null
        try{
            str.toString();     //NullPointerException
            System.out.println("Hogehoge");
            return "Die Rückkehr von der Try-Klausel.";
        }catch(Exception e){
            System.out.println("Fuga Fuga");
            return "Die Rückkehr von der Catch-Klausel.";
        }finally{
            System.out.println("Die finally-Klausel wurde ausgeführt.");
            return "Ich werde die Ausnahme quetschen";//Machen Sie eine Rückkehr
        }
    }
}

System.out


Start!
Fuga Fuga
Die finally-Klausel wurde ausgeführt.
Ich werde die Ausnahme quetschen

try-with-resources

Es kann von Java 7 aus verwendet werden. Schließen Sie unnötige Syntax

Vor Java SE 7 können Sie finally-Blöcke verwenden, um sicherzustellen, dass Ressourcen geschlossen werden, unabhängig davon, ob die try-Anweisung erfolgreich oder abrupt beendet wird.

static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
  BufferedReader br = new BufferedReader(new FileReader(path));
  try {
    return br.readLine();
  } finally {
    if (br != null) br.close();
  }
}

Bei Verwendung der Anweisung try-with-resources

static String readFirstLineFromFile(String path) throws IOException {
  try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
  }
}

In diesem Beispiel lautet die in der Anweisung "try-with-resources" deklarierte Ressource "BufferedReader". Die Deklaration steht unmittelbar nach dem Schlüsselwort try in Klammern. Ab Java SE 7 implementiert die Klasse BufferedReader die Schnittstelle java.lang.AutoCloseable. Die BufferedReader-Instanz wird mit einer try-with-resource-Anweisung deklariert, sodass sie unabhängig davon geschlossen wird, ob die try-Anweisung erfolgreich oder abrupt beendet wurde (aufgrund der Methode BufferedReader.readLine, die eine IOException auslöst). Kann gemacht werden.

http://docs.oracle.com/javase/jp/7/technotes/guides/language/try-with-resources.html


"97 Dinge, die Programmierer wissen sollten" über Ausnahmen

[97 Dinge, die Programmierer wissen sollten](http://xn--97-273ae6a4irb6e2hsoiozc2g4b8082p.com/%E6%9B%B8%E7%B1%8D/%E3%83%97%E3%83%AD%E3 % 82% B0% E3% 83% A9% E3% 83% 9E% E3% 81% 8C% E7% 9F% A5% E3% 82% 8B% E3% 81% B9% E3% 81% 8D97% E3% 81 % AE% E3% 81% 93% E3% 81% A8)

プログラマが知るべき.jpg


Referenzseite

[Best Practices für die Ausnahmebehandlung in Java] (https://moneyforward.com/engineers_blog/2014/08/22/java%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E4%BE%8B%E5%A4%96%E5%87%A6%E7%90%86%E3%81%AE%E3%83%99%E3%82%B9%E3%83%88%E3%83%BB%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B9/)

Von Java überprüfte Ausnahmen sind abnormale Systeme, für die der Anrufer nicht verantwortlich ist

Verlauf der Fehlerbehandlung

Große Sünde in außergewöhnlichem Design


Ende

Recommended Posts

[Inhouse-Studiensitzung] Behandlung von Java-Ausnahmen (26.04.2017)
Java-Ausnahmebehandlung?
[Java] Ausnahmebehandlung
☾ Java / Ausnahmebehandlung
Informationen zur Behandlung von Java-Ausnahmen
Behandlung von Java-Ausnahmen
Zusammenfassung der internen Rookie-Lernsitzung [Java]
[Java] Praxis der Ausnahmebehandlung [Ausnahme]
[Java] Informationen zur Behandlung von Try-Catch-Ausnahmen
Verwendungsregeln für die Behandlung von Java-Ausnahmen
Ausnahmebehandlungstechniken in Java
[Inhouse-Studiensitzung] Grundlagen der Java-Annotation (02.11.2017) ~ Im Aufbau ~
[Memo zur Studiensitzung] Java Day Tokyo 2017
Ausnahmebehandlung
Schrittweises Verständnis der Behandlung von Java-Ausnahmen
[Für Java-Anfänger] Informationen zur Ausnahmebehandlung
Ausnahmebehandlung Ausnahme
[Inhouse-Lernsitzung] Einführung von "Readable Code"
Java (Ausnahmebehandlung, Threading, Sammlung, Datei-E / A)
try-catch-finally Ausnahmebehandlung Verwendung von Java
Informationen zur Ausnahmebehandlung
Informationen zur Ausnahmebehandlung
Lassen Sie uns Java studieren
Behandlung von Ruby-Ausnahmen
[Java] Ausnahmeinstanz
Ruby-Ausnahmebehandlung
[Java] Studiennotizen
Java 8 studieren (wiederholbar)
Java-Studienmemorandum
Java-Sitzungsumfang
Studieren Sie Java Silver 1
Memo zur Studiensitzung: Kansai Java Engineers Association 8/5 - Selenium
Fragen in Java-Ausnahmebehandlung werfen und versuchen-fangen
Informationen zur Behandlung von Ruby-Ausnahmen
Praxis der Ausnahmebehandlung (ArithmeticException)
Java Silver Study Day 1
[Java] Wirf eine Ausnahme aus
Spring Boot-Ausnahmebehandlung
Memorandum zur Javasilver-Studiensitzung
Java # 1 studieren (typischer Typ)
Meine Studiennotiz (Java)
[Java Silver] (Ausnahmebehandlung) Informationen zu den Anweisungen try-catch-finally und try-with-resource
Memo zur Studiensitzung: Kansai Java Engineers Association [Osaka] 7/12 --Cloud Native
Studiere Java # 2 (\ mark and operator)
Klassen, die eine Ausnahmebehandlung erfordern
Java Basic Learning Content 7 (Ausnahme)
Javas erste Ausnahmebehandlung (Denkmal)
Studieren Sie Java-Array, Liste, Karte
Java Silver Lernmethode Memo
[Ruby] Ausnahmebehandlung in Funktionen
Studieren Sie Java # 7 (Art der Verzweigungssyntax)
Java Study Memo 2 mit Progate
Lernen von Java mit Progate Note 1
[Milight Design Inhouse Study Group # 5] Lesen Sie docker-compose.yml und Dockerfile Zeile für Zeile
(Lernnotiz) Java 2. Klasse Maßnahmen: Q4 Hauptpunkte (Ausnahmebehandlung)
[Einführung in Java] Informationen zur Ausnahmebehandlung (try-catch-finally, aktivierte Ausnahme, nicht aktivierte Ausnahme, Würfe, Würfe)
Eine Geschichte über das Schreiben einer Verhältnisberechnung in einer internen Lernsitzung