Intellij null checking: unreachable statements - java

This question is similar to this one, but the focus is somewhat different
I have a function that loads a file on disk in a try catch block. Because the file is crucial to the program, it will terminate if it fails to load the file:
String loadSuperImportantFile() {
try {
// ... file loading code ...
assert fileContent != null;
return fileContent;
} catch(IOException ex) {
System.err.println("Failed to load super important file. Please check path.");
System.exit(Codes.FAIL); // terminate the program
}
return null; // statement is unreachable
}
IntelliJ IDEA does not recognize that it is impossible for this function to return null. Because of this, I get warnings whenever I use the return string:
foo(loadSuperImportantFile()); // WARNING: Argument "loadSuperImportantFile()" might be null.
From reading the question I linked up above, I believe it may be possible to use Method Contracts to tell IntelliJ that the method cannot return null. I tried using the #Contract("null -> fail") decorator, but the warnings did not disappear.
Does anyone have an ideas on how to make the warnings disappear in the method itself, using a Method Contract or something similar, rather than null checking externally?

System.exit(Codes.FAIL); is not a terminating statement in Java (like return or throw).
In some wired cases, you could imagine, that it is possible to override exit method (or mock it), in such a way it doesn't terminate the application. Then this null would be returned.
For a concise and robust application, if you want to terminate the application, throw an Exception that would propagate up. Especially, if you want to terminate your application because an error occurred (invalid path). It would be even more pragmatic, to let the application die on it's own. Why do you have to call System.exit();?
PS: You can also see the answers of #Stephen C or #user31601, and that would surely fix your problem with method returning null (because it uses flow control statement - throw), but I wouldn't suggest that option. In my opinion, it would be better to design a better structue, one that is concise, and doesn't let such situation occur - in opposite to allow it to happen, and then throw AssertionException when it does.
PS2: You could also add #NotNull like #yole suggested, but again - instead of reacting to thing that shouldn't happen - just don't let it happen. And throw (for example) throw new InvalidPathException();.
My suggestion:
String loadSuperImportantFile() {
try {
return fileContent;
} catch(IOException ex) {
throw new ImportantFileMissingException("Failed to load super important file. Please check path.");
}
}
class ImportantFileMissingException extends RuntimeException {}

IntelliJ IDEA does not recognize that it is impossible for this function to return null.
IntelliJ is simply following the standard Java reachability rules. These say that the return null; statement is reachable.
Does anyone have an ideas on how to make the warnings disappear in the method itself.
You could replace the last statement with this:
throw new AssertionError("unreachable statement executed");
Or better still, put it after the System.exit(...) call.
Any unchecked exception would do, but to my mind an AssertionError is the strongest indication that something totally wrong has happened. Note that you need to explicitly throw the exception. Using an assert is not sufficient to avoid the need for a return ... since assertion checking can be turned off.
The runtime cost of a throw statement that is never executed is minimal to zero.
Another idea is to return a dummy non-null value. In this example, an empty string would do.
The problem with annotating the method as #NotNull is that a static code analyzer (using the same incomplete logic as IntelliJ) may flag that the method does return null. If you can suppress that warning, there is also the possibility that some framework might insert a runtime check for null ... which 1) serves no purpose and 2) maybe can't be optimized away.
Unfortunately, there is no practical way to tag System.exit with an annotation that says "this statement never returns". Why? Because it is a standard method, and you can't change it ... without hacking the class libraries and (potentially) breaking portability.
The best you can do (I think) to fix the problem would be to develop and submit a patch to the Intellij maintainers. One that "understands" the special behavior of System.exit.
Finally, it is generally speaking a bad idea for a library method to call System.exit in a method like in your example. A better approach is to throw a custom exception which you catch at / near the base of the call stack ... on the application's controlling thread. That way, you can have all of the code and logic that governs (controlled) application exit in the same place.
A subsidiary method should not be deciding about the "fate" of the overall application.

Why don't you just add a terminating statement to the end of catch block? It will never be reached, so all it should do is help the compiler infer that the final return statement isn't necessary.
For example:
String loadSuperImportantFile() {
try {
// ... file loading code ...
assert fileContent != null;
return fileContent;
} catch(IOException ex) {
System.err.println("Failed to load super important file. Please check path.");
System.exit(Codes.FAIL); // terminate the program
throw new AssertionError("Unreachable");
}
}

Simply annotate the method as #NotNull. The #Contract annotation you've tried to apply says that the method will fail if you pass null to it as a parameter, which does not make sense because it does not have any parameters.

You could also return an Optional<String> instead of a String.
This way, you could avoid returning null and return an Optional.empty() instead to avoid null checking and possible NullPointerException.
See: https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html

Related

Is a method that returns a Try allowed to throw?

We're using Vavr in our project to ease exception handling. I always make sure that a method that returns a Try can never throw anything, like so:
public Try<Result> someSafeMethod() {
return Try.of(() -> someService.generateId())
.map(someOtherService::getValueForId)
.map(mappingService::mapToResult);
}
but some of my colleagues would implement it like this:
public Try<Result> someSafeMethod() {
String generatedId = someService.generateId(); // <- Might throw an Exception that is not caught by the Try clause
return Try.of(() -> someOtherService.getValueForId(generatedId))
.map(mappingService::mapToResult);
}
Arguing that if something is wrong with the generation of the ID that they would rather the exception is thrown instead of the returned Try being a failure.
The documentation does not prohibit that a method returning a Try should not throw, but it does state that:
Try is a monadic container type which represents a computation that may either result in an exception, or return a successfully computed value.
Am I being too too strict? Imagine you would use an API where all methods return a Try, wouldn't it be bad when they still throw?
You are not being too strict.
The whole point of using Try as a return value is the resulting benefit of programming with total functions and having a composable way of handling errors. Total functions are functions that always return a value of the declared return type for all possible argument values. If they are throwing exceptions, their functions are not total functions anymore, and—without explicit error handling—non-totality will propagate transitively through their code, 'infecting' all other functions that call them with non-totality. As a result, they will end up with code that will be much harder to reason about and it will take more effort to make sure it is correct.
Throwing exceptions while using Try would also defy the purpose of using Try in the first place and it would unnecessarily complicate the code consuming their API for no obvious benefit, because the API consumers will have to do error handling both using Try and catching exceptions.

Shouldn't catch NPE but don't know how to handle the NULL

I know that NPE is not recommended to be caught, however the NPE is in a method whose return value is a boolean based on the variable where the NPE comes from.
Code is something like this:
public static boolean isStale() {
return a.get(); //a==null causing NPE
}
In my case, I don't really know what to return without the info of a.
What should I do? What kind of exception should I throw, if any?
Edit:
1. returning true or false will be inaccurate because the result really depends on the info inside a.
a is acctually from a service call client.getA()
There is no reason why you should prevent your code from throwing exceptions. Just consider your case : you say yourself that the behaviour of your method is not defined in the case a == null, so why should you handle it ? It will only lead to weird behaviours and your users might be surprised that their code failed or produce unexpected results somewhere whereas their calls into your API went fine.
Exceptions are specially designed to address this kind of things, so make good use of it. You can either throw a new, custom exception to add some API-specific semantic, or let the NPE be propagated to the caller.
For example :
public static boolean isStale() {
if (a == null) throw new IllegalStateException("a should not be null");
return a.get();
}
However, it is more likely that you should do that in a constructor (because I assume a is an attribute). In a constructor, I would opt for IllegalArgumentException.
First you need to ask yourself: Is it normal for a to ever be null?
If yes, then throwing an exception is rarely a good idea. Exceptions should really only be thrown when something unexpected occurs. It then really is up to you to decide what this means for your program. Does it make sense to return some default value in this case?
return a == null ? false : a.get(); // return false as a default value?
If no (more likely):
... then ask the following question: Why am I getting a null value?
If it's because you coded a bug: then you don't need to do anything. Just let it throw a NullPointerException. There really is no point in catching the exception and pretending everything is alright, if clearly, a basic invariant in your program has been broken. Better to let it throw the exception early and focus your energies on understanding and fixing the bug asap. Trying to handle the exception will only cause your program to fail at some other more unexpected point in time, and will become that much harder to debug.
If, on the other hand, it's because of some external entity feeding you bad data over which you really have no control: then this could be a good case for throwing a custom exception that can be used to provide a more meaningful error message to either the user or the developer. But even in this case, it's probably a better idea to have a validated for a null value more "upstream" and have it throw an exception as early as possible. It doesn't feel like it should be part of the isStale() method's contract to worry about the correctness of a's value.
Interesting reading, geared towards C#, but the principles apply just as well to Java: Vexing exceptions.
This depends on what isStale() determines. You can try/catch this method and catch the NullPointerException. I don't believe this violates best practices if you really have no way to handle a being null. You could also instantiate a new a if a is null, or throw your own Exception.
There's no need to throw any Exception just make sure a isn't null before using it, use a simple conditional statement:
public static boolean isStale() {
a!=null ? return a.get() : return false;
}
In the case where returning false will be irrelevant, you can just change the return type of your method to String and return a warning or any other significant message :
public static String isStale() {
a!=null ? return a.get().toString() : return "NULL";
}
Take a look at this: Best approach to converting Boolean object to string in java

Should I use precondition checks to check intermediate results?

Guava offers helper functions to check the preconditions but I could not find helper functions to check intermediate results.
private void foo(String param)
{
checkNotNull(param, "Required parameter is not set");
int x = get(param);
if (x == -1) {
throw new RuntimeException("This should never have happened and indicates a bug.");
}
}
Should I wrap the if (...) {....} part in my own helper?
Or should I use checkState from Guava?
Or should I view the failure of get() as a consequence of param and use checkArgument?
Should I use asserts in these cases?
Or am I missing something?
It's somewhere between a matter of preference and a matter of convention.
Generally, people will use asserts to indicate programming errors; that is, "if I did my job right, then a non-null param should never result in a -1 from get, regardless of user input or other outside forces." I treat them almost as comments that can optionally be verified at runtime.
On the other hand, if get might return -1 in some cases, but that input is invalid, then I would generally throw an IllegalArgumentException, and checkArgument is a perfectly reasonable way to do this. One drawback this has is that when you later catch that, it could have come from pretty much anywhere. Consider:
try {
baz();
bar();
foo(myInput);
} catch (IllegalArgumentException e) {
// Where did this come from!?
// It could have come from foo(myInput), or baz(), or bar(),
// or some method that any of them invoked, or really anywhere
// in that stack.
// It could be something totally unrelated to user input, just
// a bug somewhere in my code.
// Handle it somehow...
}
In cases where that matters -- for instance, you want to pop up a helpful note to the user that they're not allowed to enter -1 in their input form -- you may want to throw a custom exception so that you can more easily catch it later:
try {
baz();
bar();
foo(myInput);
} catch (BadUserInputException e) {
reportError("Bad input: " + e.getMessage());
log.info("recorded bad user input", e);
}
As for checkState, it doesn't really sound right to me. That exception usually implies that the problem was the state that this was in (or some other, more global state in the application). From the docs:
Signals that a method has been invoked at an illegal or inappropriate time.
In your case, a -1 is never appropriate, so checkState is misleading. Now, if it had been:
if (x == -1 && (!allowNegativeOne()) { ... }
...then that would be more appropriate, though it still has the drawback that IllegalArgumentException had above.
So, lastly, there's the question of whether you should just keep the if as it is, or use a helper method. That really comes down to taste, how complex the check is, and how often it's used (e.g. in other methods). If the check is as simple as x == -1 and that check isn't ever performed by other methods (so code reuse is not an issue), I would just keep the if.
If the get method is simply converting the string to an int, then it should do the validation there, preferably throwing an illegalArgumentException or some such RuntimeException. With the above you are also mixing levels of abstraction in your method. E.g. your checkNotNull abstracts away the checking of param for null, but the checking for param as an int is split across the get method and the foo method. Why not have one checkPreCondition type method? E.g.
private void paramShouldBeNonNullInt(String value) {
if (value == null) throw new IllegalArgumentException("value was null");
try {
Integer.parseInt(value)
} catch (NumberFormatException e) {
throw new IllegalArgumentException("value was not an integer");
}
}
First of all you need to make a distinction between contracts (e.g assertions/programming errors) and error handling (e.g. recoverable exceptions that could and should be caught and recovered from).
If you have the need to check an intermediate result, it seems like you don't trust the invoked service and you want to make sure your assumptions hold. Right? This should be expressed as an assertion, and Guava don't have very good support for that.
Have a look at valid4j. Found here https://github.com/helsing/valid4j and here http://www.valid4j.org.
I would then have expressed the code like this (using valid4j's support for hamcrest-matchers):
private int getFoo(String param) {
require(param, notNullValue()); // Violation means programming error at client
int x = get(param);
ensure(x, not(equalTo(-1)); // Violation means programming error at supplier
return x;
}
Some other excellent answers here.
From the Preconditions javadoc:
Precondition exceptions are used to signal that the calling method has made an error. (...) Postcondition or other invariant failures should not throw these types of exceptions.
So ...
Should I wrap the if (...) {....} part in my own helper?
No, existing facilities should be good enough.
Or should I use checkState from Guava?
Yes possibly: if parameters need to be loaded from a file before this method is called, then that would be part of the contract of how this class must be used.
Or should I view the failure of get() as a consequence of param and use checkArgument?
Yes possibly: e.g. if there was some formatting restriction on the syntax of parameters. (Although perhaps that would go inside get())
Should I use asserts in these cases?
Yes. If it's not a precondition check like the above, then normally I'd just use an assert here. Don't forget you can still add a message:
assert x != 1 : "Indicates a bug.";
I find this appropriate to document expectations and verify the internal / private implementation of a class or method.
If you want to make that a runtime check, you could do if (...) throw AssertionError but that's probably only necessary if you're working with dodgy code that you don't trust.

Appropriate use of assert

Can you please help me better understand, what is an appropriate use of “assert” vs “throwing an exception? When is each scenario appropriate?
Scenario 1
CODE
public Context(Algorythm algo) {
if (algo == null) {
throw new IllegalArgumentException("Failed to initialize Context");
}
this.algo = algo;
}
TEST
public void testContext_null() {
try {
context = new Context(null);
fail();
} catch (IllegalArgumentException e) {
assertNotNull(e);
}
}
Scenario 2
CODE
public Context(Algorythm algo) {
assert (algo != null);
this.algo = algo;
}
TEST
public void testContext_null() {
try {
context = new Context(null);
fail();
} catch (AssertionFailedError e) {
assertNotNull(e);
}
}
The main difference with assert is;
the ability to turn on/off selected tests by class/package.
the error thrown.
assert is more approriate for tests which will be turned off in production.
If you want a test which is checked every time, esp if validating data from an input, you should use the check which runs every time.
Assert is a macro (in C/C++, or a function in other languages) that validates a given expression as true or false, and throw an exception in case of false values.
Assert is something to use when ddebugging an application, like when you must check if a math expression really gives you an appropriate value, or if an object/structure member is not null or missing something important, and things like that.
An Exception throwing is more of a real error treatment. Exceptions are errors too and can stop your application, but they are used as the (let's say) "retail version" error treatment of the application. That's because Exceptions can be caught and taken differently to the user, with a little non-technical message instead of symbols and memory addresses, while you can just serialize that into an app log, for example.
On the other hand, asserts will just stop the running process and give you a message like "Assertion failed on source_file.ext, line X. The process will be terminated." And that's not user-friendly :)
The assert keyword should be used when failure to meet a condition violates the integrity of the program. These are intended to be non-recoverable error situations.
Exceptions, on the other hand, alert calling methods to the presence and location of an error but can be handled or ignored at the programmer's discretion.
When testing, you should use the Assert functions when a condition must be met for a test to pass. If you're expecting an exception in that particular test, JUnit 4 has an annotation to signify that an test should throw a particular Exception:
#Test(expected=MyException.class)
Outside of test code, asserts are generally a bad idea. the reason is that unless there are very strict company guidelines in place, you invariably end up with mixed usage, which is bad. there are basically 2 usage scenarios for assert:
extra, possibly slow tests which will be turned off in production
normal, quick code sanity tests which should never be disabled (like requiring a given method parameter to be non-null)
As long as you always follow one of the scenarios, things are fine. however, if your code base ends up with both scenarios, then you are stuck. you have asserts which follow scenario 2 which you don't want to disable, and you have asserts which follow scenario 1 (and are slowing down your production code) which you want to disable. what to do?
most codebases which i have worked with which used asserts in normal code, never ended up disabling them in the production build for exactly this reason. therefore, my recommendation is always to avoid them outside of test code. use normal exceptions for the normal code, and stick the extra, possibly slow code (with asserts) in separate test code.

Is returning null after exception is caught bad design [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I always come across the same problem that when an exception is caught in a function that has a non-void return value I don't know what to return. The following code snippet illustrates my problem.
public Object getObject(){
try{
...
return object;
}
catch(Exception e){
//I have to return something here but what??
return null; // is this a bad design??
}
}
So my questions are:
Is return null bad design?
If so what is seen as a cleaner solution??
thanks.
I would say don't catch the exception if you really can't handle it. And logging isn't considered handling an error. Better to bubble it up to someone who can by throwing the exception.
If you must return a value, and null is the only sensible thing, there's nothing wrong with that. Just document it and make it clear to users what ought to be done. Have a unit test that shows the exception being thrown so developers coming after you can see what the accepted idiom needs to be. It'll also test to make sure that your code throws the exception when it should.
I always come across the same problem that when an exception is caught in a function that has a non-void return value I don't know what to return.
If you don't know what to return, then it means that you don't know how to handle the exception. In that case, re-throw it. Please, don't swallow it silently. And please, don't return null, you don't want to force the caller of the code to write:
Foo foo = bar.getFoo();
if (foo != null) {
// do something with foo
}
This is IMHO a bad design, I personally hate having to write null-checks (many times, null is used where an exception should be thrown instead).
So, as I said, add a throws clause to the method and either totally remote the try/catch block or keep the try/catch if it makes sense (for example if you need to deal with several exceptions) and rethrow the exception as is or wrap it in a custom exception.
Related questions
How to avoid “!= null” statements in Java?
Above all I prefer not to return null. That's something that the user has to explicitly remember to handle as a special case (unless they're expecting a null - is this documented). If they're lucky they'll deference it immediately and suffer an error. If they're unlucky they'll stick it in a collection and suffer the same problem later on.
I think you have two options:
throw an exception. This way the client has to handle it in some fashion (and for this reason I either document it and/or make it checked). Downsides are that exceptions are slow and shouldn't be used for control flow, so I use this for exceptional circumstances (pun intended)
You could make use of the NullObject pattern.
I follow a coding style in which I rarely return a null. If/when I do, that's explicitly documented so clients can cater for it.
Exceptions denote exceptional cases. Assuming your code was supposed to return an object, something must have gone wrong on the way (network error, out of memory, who knows?) and therefore you should not just hush it by returning null.
However, in many cases, you can see in documentation that a method returns a null when such and such condition occurs. The client of that class can then count on this behaviour and handle a null returned, nothing bad about that. See, in this second usage example, it is not an exceptional case - the class is designed to return null under certain conditions - and therefore it's perfectly fine to do so (but do document this intended behaviour).
Thus, at the end of the day, it really depends on whether you can't return the object because of something exceptional in your way, or you simply have no object to return, and it's absolutely fine.
I like the responses that suggest to throw an exception, but that implies that you have designed exception handling into the architecture of your software.
Error handling typically has 3 parts: detection, reporting, and recovery. In my experience, errors fall into classes of severity (the following is an abbreviated list):
Log for debug only
Pause whatever is going on and report to user, waiting for response to continue.
Give up and terminate the program with an apologetic dialogue box.
Your errors should be classified and handling should be as generically and consistently as possible. If you have to consider how to handle each error each time you write some new code, you do not have an effective error handling strategy for your software. I like to have a reporting function which initiates user interaction should continuation be dependent on a user's choice.
The answer as to whether to return a null (a well-worn pattern if I ever saw one) then is dependent on what function logs the error, what can/must the caller do if the function fails and returns the null, and whether or not the severity of the error dictates additional handling.
Exceptions should always be caught by the controller in the end.
Passing a <null> up to the controller makes no sense.
Better to throw/return the original exception up the stack.
It's your code and it's not bad solution. But if you share your code you Shoudn't use it because it can throw unexpected exception (as nullpointer one).
You can of course use
public Object getObject() throws Exception {}
which can give to parent function usable information and will warn that something bad can happen.
Basically I would ditto on Duffymo, with a slight addition:
As he says, if your caller can't handle the exception and recover, then don't catch the exception. Let a higher level function catch it.
If the caller needs to do something but should then appropriately die itself, just rethrow the exception. Like:
SomeObject doStuff()
throws PanicAbortException
{
try
{
int x=functionThatMightThrowException();
... whatever ...
return y;
}
catch (PanicAbortException panic)
{
cleanUpMess();
throw panic; // <-- rethrow the exception
}
}
You might also repackage the exception, like ...
catch (PanicAbortException panic)
{
throw new MoreGenericException("In function xyz: "+panic.getMessage());
}
This is why so much java code is bloated with if (x!=null) {...} clauses. Don't create your own Null Pointer Exceptions.
I would say it is a bad practice. If null is received how do I know if the object is not there or some error happened?
My suggestion is
never ever return NULL if the written type is an array or
Collection. Instead, return an empty Collection or an empty array.
When the return type is an object, it is up to you to return null depending on the scenario. But never ever swallow an exception and return NULL.
Also if you are returning NULL in any scenario, ensure that this is documented in the method.
As Josha Blooch says in the book "Effective Java", the null is a keyword of Java.
This word identifies a memory location without pointer to any other memory location: In my opinion it's better to coding with the separation of behavior about the functional domain (example: you wait for an object of kind A but you receive an object of kind B) and behavior of low-level domain (example: the unavailability of memory).
In your example, I would modify code as :
public Object getObject(){
Object objectReturned=new Object();
try{
/**business logic*/
}
catch(Exception e){
//logging and eventual logic leaving the current ojbect (this) in a consistent state
}
return objectReturned;
}
The disadvantage is to create a complete Object in every call of getObject() (then in situation where the object returned is not read or write).
But I prefer to have same object useless than a NullPointerException because sometimes this exception is very hard to fix.
Some thoughts on how to handle Exceptions
Whether returning null would be good or bad design depends on the Exception and where this snippet is placed in your system.
If the Exception is a NullPointerException you probably apply the catch block somewhat obtrusive (as flow control).
If it is something like IOException and you can't do anything against the reason, you should throw the Exception to the controller.
If the controller is a facade of a component he, translate the Exception to well documented component-specific set of possible Exceptions, that may occur at the interface. And for detailed information you should include the original Exception as nested Exception.

Categories