Generally speaking, the Java compiler does not propagate the information that a method "always" throw an Exception, and therefore, does not detect that all code paths are complete.
(This is due to the fact that Java compiler compiles each class independently).
It's a problem when you want to write something like that.
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"); } }
(ie, a kind of "assertion helper" that gathers context information).
Because the compiler will complain that myMethod does not always return a MyObject.
To my knowledge, there is no specific annotation to indicate that a method always throws.
The calculate method should check for an exception and if there is no exception, return the calculated value to the main function i.e. v1+v2 or v1-v2; Else if an exception exists then it should print the error statement and the value that is returned from the calculate method to the main method should be 0.0(Not ...
Unchecked exceptions can be propagated in the call stack using the throw keyword in a method. Checked exceptions can be propagated using the throw keyword when the method that throws the exception declares it using the throws keyword.
Compiler does not know what type of exception it just take that instance and then find out the its type using reflection then print the stack's trace on console.
- The main method should simply terminate if any exception occurs. The throws clause only states that the method throws a checked FileNotFoundException and the calling method should catch or rethrow it. If a non-checked exception is thrown (and not catch) in the main method, it will also terminate.
A simple workaround is to let your fatalISE
method not throw the exception, but only create it:
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"); } }
This way the compiler will know not to complain about a missing return
. And forgetting to use the throw
is unlikely, exactly because the compiler will usually complain.
A trick that I use is to replace
public void fatalISE(String message) { String context = "gather lots of information about the context of the error"; throw new IllegalStateException(context +": " + message); }
with
public <T> T fatalISE(String message) { String context = "gather lots of information about the context of the error"; throw new IllegalStateException(context +": " + message); }
Then, in myMethod, use:
public MyObject myMethod() { if (allIsGood()) { return new MyObject(); } return ErrorContext.fatalISE("all is not good"); }
It will work whatever the return type of myMethod, including primitive types. You can still use fatalISE
in a void method, by just not using the return
keyword.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With