2013-02-22 5 views
16

Im Allgemeinen propagiert der Java-Compiler nicht die Information, dass eine Methode "immer" eine Exception auslöst und daher nicht erkennt, dass alle Codepfade vollständig sind .Ist es möglich, dem Compiler mitzuteilen, dass eine Methode immer eine Exception auslöst

(Dies ist aufgrund der Tatsache, dass Java-Compiler jede Klasse unabhängig kompiliert).

Es ist ein Problem, wenn Sie so etwas schreiben möchten.

public class ErrorContext { 
    public void fatalISE(String message) { 
     String context = "gather lots of information about the context of the error"; 
     throw new IllegalStateException(context +": " + message); 
    } 
} 

public class A { 
    public MyObject myMethod() { 
     if (allIsGood()) { 
      return new MyObject(); 
     } 
     ErrorContext.fatalISE("all is not good"); 
    } 
} 

(dh eine Art "Assertion Helper", die Kontextinformationen erfasst).

Da der Compiler beschweren wird, dass myMethod nicht immer ein MyObject zurückgibt.

Nach meinem Wissen gibt es keine spezifische Anmerkung, die angibt, dass eine Methode immer ausgelöst wird.

+1

Eine Lösung in einem anderen Beitrag [hier] (http://stackoverflow.com/a/11249665/1402846). – Pang

Antwort

30

Eine einfache Abhilfe ist Ihr fatalISE Methode nicht throw die Ausnahme zu lassen, aber es nur schaffen:

public class ErrorContext { 
    public IllegalStateException fatalISE(String message) { 
     String context = "gather lots of information about the context of the error"; 
     return new IllegalStateException(context +": " + message); 
    } 
} 

public class A { 
    public MyObject myMethod() { 
     if (allIsGood()) { 
      return new MyObject(); 
     } 
     throw ErrorContext.fatalISE("all is not good"); 
    } 
} 

Auf diese Weise wird der Compiler weiß nicht, über eine fehlende return zu beklagen. Und zu vergessen, die throw zu verwenden, ist unwahrscheinlich, genau weil der Compiler sich normalerweise beschweren wird.

+6

Dies hat den Vorteil * * großer Klarheit beim Lesen des Codes. –

+0

lesbar, einfach und sicher. Groß ! – Zorglub

7

Ein Trick, den ich verwende

public void fatalISE(String message) { 
    String context = "gather lots of information about the context of the error"; 
    throw new IllegalStateException(context +": " + message); 
} 

mit

public <T> T fatalISE(String message) { 
    String context = "gather lots of information about the context of the error"; 
    throw new IllegalStateException(context +": " + message); 
} 

Dann in myMethod, zu verwenden, ersetzen ist:

public MyObject myMethod() { 
    if (allIsGood()) { 
     return new MyObject(); 
    } 
    return ErrorContext.fatalISE("all is not good"); 
} 

Es funktioniert unabhängig von dem Rückgabetyp myMethod einschließlich primitiver Typen. Sie können fatalISE weiterhin in einer void -Methode verwenden, indem Sie einfach das Schlüsselwort return nicht verwenden.

+2

Dies ist clever (ziemlich clever), aber ein bisschen irreführend für Leute, die den Code lesen. –

+1

Scheint, für Funktionen zu arbeiten, die Verweise zurückgeben, aber nicht primitive: Typparameter T kann nicht bestimmt werden; Für die Typvariable T gibt es keine eindeutige Maximalinstanz mit den Obergrenzen int, java.lang.Object 'in der Zeile' return this.fatalISE ("blah"); ' –

5

hinzufügen

return null; 

am Ende. (es wird es sowieso nie erreichen, aber um den Compiler zu beruhigen, sollte dies tun)

6

Wie wäre es mit der Umkehrung der if-Bedingung?

public MyObject myMethod() { 
    if (!allIsGood()) { 
     ErrorContext.fatalISE("all is not good"); 
    } 
    return new MyObject(); 
} 

Viel Glück!

0

Ich stieß gerade auf diesen Anwendungsfall, aber mit einer Methode, die immer 2 oder mehr Arten von Ausnahmen werfen sollte.

Um den Code kompilieren zu können, können Sie return null; hinzufügen, wie MouseEvent sagte.

oder besser ersetzen Sie es durch throw new AssertionError(), den Nullwert verhindert Rückkehr Lesbarkeit zu verbessern und sicherzustellen, dass, wenn jemand checkAndAlwaysThrowException() modifiziert Exception werfen weiterhin wil zu immer

public Object myMehtod() throws ExceptionType1, ExceptionType2 { 
    //.... 
    checkAndAlwaysThrowException(); 
    throw new AssertionError("checkAndAlwaysThrowException should have throw exception"); 
} 

public void checkAndAlwaysThrowException() throws ExceptionType1, ExceptionType2 { 
    if (cond) { 
     throw new ExceptionType1(); 
    } else { 
     throw new ExceptionType2(); 
    } 
} 
Verwandte Themen