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.
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.
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 Ausnahme: Eine Ausnahme, die vom Anrufer abgefangen oder ausgelöst werden muss. Eine Ausnahme, die keine Laufzeitausnahme ist.
Laufzeitausnahme: Eine Ausnahme, die der Anrufer nicht überprüfen muss. Erben Sie java.lang.RuntimeException
.
Ausnahmetypstruktur
java.lang.Exception
- IOException
- SQLException
- RuntimeException
- NullPointerException
- IllegalArgumentException
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) {
//...
}
Throws
in Methodendeklarationen.private void read(File file) throws FileNotFoundException {
FileReader fr = new FileReader(file);
}
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.
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
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
log.error (" ~ Fehler ", e);
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.
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
java.lang.Exception
fangen könnenFramework-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;
}
}
}
Throwable
ist eine Stufe höher als java.lang.Exception
.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
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 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".
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);
}
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".
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.
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
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
Nur Java implementiert geprüfte Ausnahmen in wichtigen Sprachen. Jede Inspektionsausnahme ist negativ.
http://qiita.com/Kokudori/items/0fe9181d8eec8d933c98
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
System.exit
sind in der finally-Klausel verbotenDiese 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](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)
[Das Programm nicht zum Absterben zwingen](http://xn--97-273ae6a4irb6e2hsoiozc2g4b8082p.com/%E3%82%A8%E3%83%83%E3%82%BB%E3 % 82% A4 /% E6% AD% BB% E3% 81% AC% E3% 81% AF% E3% 81% 9A% E3% 81% AE% E3% 83% 97% E3% 83% AD% E3% 82% B0% E3% 83% A9% E3% 83% A0% E3% 82% 92% E7% 84% A1% E7% 90% 86% E3% 81% AB% E7% 94% 9F% E3% 81% 8B% E3% 81% 97% E3% 81% A6% E3% 81% 8A% E3% 81% 84% E3% 81% A6% E3% 81% AF% E3% 81% 84% E3% 81% 91% E3% 81% AA% E3% 81% 84)
[Ignorieren Sie den Fehler nicht](http://xn--97-273ae6a4irb6e2hsoiozc2g4b8082p.com/%E3%82%A8%E3%83%83%E3%82%BB%E3%82%A4/%E3% 82% A8% E3% 83% A9% E3% 83% BC% E3% 82% 92% E7% 84% A1% E8% A6% 96% E3% 81% 99% E3% 82% 8B% E3% 81% AA)
[Unterscheiden Sie klar zwischen technischen und geschäftlichen Ausnahmen](http://xn--97-273ae6a4irb6e2hsoiozc2g4b8082p.com/%E3%82%A8%E3%83%83%E3%82%BB%E3%82 % A4 /% E6% 8A% 80% E8% A1% 93% E7% 9A% 84% E4% BE% 8B% E5% A4% 96% E3% 81% A8% E3% 83% 93% E3% 82% B8% E3% 83% 8D% E3% 82% B9% E4% BE% 8B% E5% A4% 96% E3% 82% 92% E6% 98% 8E% E7% A2% BA% E3% 81% AB% E5% 8C% BA% E5% 88% A5% E3% 81% 99% E3% 82% 8B)
[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
Große Sünde in außergewöhnlichem Design