Why does Intellij idea warn about nullpointer in that if condition? - java

Here is my code
if (!multipartFile.isEmpty() && multipartFile.getOriginalFilename() != null && !multipartFile.getOriginalFilename().isBlank()) {
String fileName = StringUtils.cleanPath(multipartFile.getOriginalFilename());
dishCreationDto.setImageFileName(fileName);
dishService.saveWithFile(dishCreationDto, multipartFile);
} else {
dishService.save(dishCreationDto);
}
Here is how I see that code
As you can see, the last part of IF condition is underlined as Idea thinks that getOriginalFilename can return null, but I've checked this with that line of a code
multipartFile.getOriginalFilename() != null. What am I doing wrong?

Idea thinks that getOriginalFilename can return null
Because it can.
but I've checked this with that line of a code multipartFile.getOriginalFilename() != null
You checked that the previous invocation did not return null. The next one still can.
What am I doing wrong?
Calling a method twice in rapid succession, instead of storing its result in a variable and using that one for the check and the further processing. In fact you then call it for a 3rd time.
(this was just a copy of my comment from above)
While there may be ways to simplify the condition as the other answer shows, as you also need the result of getOriginalFilename() inside the if, I would assume the IDE will complain about that one next, and at the end you will probably have to bite the bullet and have a variable for it:
String originalFilename = multipartFile.getOriginalFilename();
if (!multipartFile.isEmpty() && originalFilename != null && !originalFilename.isBlank()) {
String fileName = StringUtils.cleanPath(originalFilename);
dishCreationDto.setImageFileName(fileName);
dishService.saveWithFile(dishCreationDto, multipartFile);
} else {
dishService.save(dishCreationDto);
}

You could simplify that expression by using the StringUtils:
!StringUtils.isNullOrEmpty(multipartFile.getOriginalFilename())
There are other functions in that utility class that might be helpful depending on what you're trying to do.
IntelliJ isn't always right but is always good to look a bit more in detail to our code to see what can be improved/simplified for better debugging/readability.

Related

Reducing conditions within a if statement

I have a code snippet as below. Here there is a nested if else loop as well as multiple conditions [all different parameters]. What is the best way to optimize this.
if(request!=null && !StringUtils.isBlank(request)) {
if(request.getFirstName()!=null && !StringUtils.isBlank(request.getFirstName())
&& request.getLastName()!=null && !StringUtils.isBlank(request.getLastName())
&& request.getAge()!=null && !StringUtils.isBlank(request.getAge())
&& request.getAddress()!=null && !StringUtils.isBlank(request.getAddress())
&& request.getPhoneNumber()!=null && !StringUtils.isBlank(request.getPhoneNumber())) {
return true;
}else {
return false;
}
}else {
return false;
}
I had thought of using switch case and for loop as well but all the conditions are based on different variables, I didn't see it as compatible.
StringUtils from commons-lang already has a method which accepts an array of Strings. It will check for null or empty or blank strings. So all your checks boil down to:
return !(request == null || StringUtils.isAnyBlank(
request.getFirstName, request.getLastName,
request.getAge, request.getPhoneNumber));
You can try StringUtils.isAnyBlank(). Please refer attached link.
isAnyBlank : https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#isAnyBlank-java.lang.CharSequence
If you don't use commons-lang dependency you can simply use Stream API (Java 8+)
Boolean allNonBlank = Stream.of(
request.getFirstName(),
request.getLastName(),
request.getAge(),
request.getPhoneNumber())
.allMatch(it -> it != null && !String.isBlank(it));
You have a few syntax errors
You are passing request to StringUtils but it doesn't appear to implement CharSequence
You are using !! instead of !
You invocation of the get methods does not include the () to mark it as methods.
Although not an error, you do not need nested if-statements here. Using unnecessary if-else-blocks can make it harder to decipher what the code is doing. It can, however, allow for comments to describe why certain conditions are being checked or whatever. None of that seems relevant here. In fact, you can pass the result of the boolean operation without any if-statement. Using if-statements that return true or false looks like this.
if (<condition-is-true?>) return true
else return false;
Which can be simplified to...
return <condition-is-true?>;
Further, assuming you are using using Apache StringUtils, you do not need to check for null first - the isEmpty(CharSequence) method does that. Additionally, StringUtils includes the isAnyEmpty(CharSequence...) method so you can pass all of the Strings at once.
return request != null && !StringUtils.isAnyEmpty(
request.getFirstName(),
request.getLastName(),
request.getAge(),
request.getAddress(),
request.getPhoneNumber());

Checking for NullPointerException, correctness or personal belief?

In my code, I am making a lot of checks for null so that I don't get a NullPointerException usually i am just doing like this:
if(variable != null){
//do something with the variable
}
Is the following better in any way or is it just a matter or personal belief?
if( !variable.equals(null) ){
//do something with the variable
}
Is there a more efficient way to make this check?
Btw I do have done my research already but I cant seem to find concrete evidence to prove either point.
P.S This is a NOT duplicate of Avoiding != null statements, on that the best answer is that you should either use Assert, which cannot be used to run code rather than just display a message, or actually throw the exception which I dont want either. This post is addressing a different issue of the same subject.
if(!variable.equals(null) ){
//do something with the variable
}
If variable is null NPE occurs. First method is far better.
EDIT:
Using Optional:
Consider that you have Person object and want to getSalary(). Unfortunately age can be null - in that case you want default value. You can do Integer salary = Optional.ofNullable(person.getSalary()).orElse(2000). It will return salarty from person or 2000 in case salary is null.
Or you can use java.util.Optional from Java 8.
Very nice examples are on JavaCodeGeeks.
Optional is usually used in java.util.stream lambdas for "functional-style operations".
As others already said, the variant
if(!variable.equals(null))
can NPE itself when variable is null. Furthermore, you have to be sure that the equals method also is null-safe for all object types you use. Thus, if you absolutely need to check, use ==.
As for better solutions (we're going opinion-based here): I think that this ecessive null-checking is a sign of brittle software and suboptimal interface definition. What I currently try to do more and more is use the javax.validation annotation #NotNull to harden my interfaces and get rid off all these runtime checks:
private #NotNull String getName() {...} // guaranteed not to return null
...
if(getName() == null) { // superfluos, your IDE gives a shout if configurd correctly
...
}
... give it a shot :)
Edit (as an answer to the comment, as I need code-formatting):
Here's a complete cut&paste-example from my current eclipse setup:
package stuff;
import javax.validation.constraints.NotNull;
public class Try3 {
public #NotNull String getName() { return ""; }
public void test() {
if(getName() == null)
System.out.println("Cannot happen due to contract");
}
}
Ensure, that the imported type is indeed javax.validation.constraints.NotNull (as other frameworks also have a NotNull annotation, which may be defined in a different way). For eclipse, you also have to check "Enable annotation-based null analysis" in the project settings under JavaCompiler / Errors/Warnings and customize the annotations to use, as eclipse defaults to some home-brewed annotations. The customization can be accessed via the link "Configure" after the checkbox for using default annotations in the same settings page. Hope that helps!
There are two approaches:
public void calculate(Class variable) {
Assert.notNull(variable, "variable was null");
//calculations
}
//and
if (variable == null) {
//bad
} else {
calculate(variable);
}
The second one is the most common one. If your variable is a String consider using Guava.StringUtils with it's fantastic isBlank method which checks if the String is null or ""
Summarizing:
if (variable == null) {
//bad
} else {
//good
}
The above is standard approach. The better approach will be:
private boolean isNull(Class variable) {
return variable == null;
}
if (isNull(variable)) {
} else {
}
I used to do call the below method all the time which checks for nullpointer exception
public static boolean isAvailable(Object data) {
return ((data!=null) && (data.toString().trim().length() > 0));
}

IntelliJ IDEA Reporting Contract Violation Warning

Here is the Java code:
public static boolean anyEqual(Object needle, Object... haystack) {
if(needle == null || haystack == null) {
return false;
}
if(haystack.length == 0) {
return false;
}
for(Object match : haystack) {
if(match != null && needle.getClass() == match.getClass() && needle.equals(match)) {
return true; // warning from IntelliJ here, 'contract clause !null, null -> false is violated'
}
}
return false;
}
Does anyone have any idea why this is being shown? contract clause !null, null -> false is violated? Thanks!
IntelliJ 14.0.2 build: 139.659
Screenshot:
IntelliJ is inferring the formal contract of your method to be this:
null, _ -> false; !null, null -> false
What this actually means:
The first contract specifies that, so long as the first parameter is null, it will return false. This is observed by your first if statement:
if(needle == null || haystack == null) {
return false;
}
The second contract specifies that, if the second parameter is null, then it will return false. This is also specified by the same if statement above.
My gut is telling me that IntelliJ is having some trouble discerning what the loop's formal contract is in addition to all of the above, although it'd be as simple as another condition in the contract expression.
for(Object match : haystack) {
if(match != null && needle.getClass() == match.getClass() && needle.equals(match)) {
return true;
}
}
Let's briefly go through this.
The enhanced-for statement won't fire if haystack is of length 0, so that's something to take into consideration.
The elements inside of the array could be null, and I'm not entirely sure that IntelliJ's static analysis covers that piece yet.
We've established already that needle must be non-null, so there's nothing violating the contract at that line.
If we have a scenario in which match != null && needle.getClass() == match.getClass() && needle.equals(match) is true, we return true. Otherwise, we return false.
There's nothing that I can see in the formal documentation that gives us the expression we require to say, "hey - we're checking elements of an array!"; it may be the case that the analysis is tripping up on the fact that we're returning true in spite of what we stated above (since haystack is non-null).
Allow me to stress this point:
haystack has to be non-null in order for you to enter into the enhanced-for. Your code will not work otherwise.
All in all, I wouldn't worry about it. Better yet, file a bug against it so that this sort of thing could be fixed or expanded upon.
This looks like an IntelliJ bug to me, since by removing the static keyword from the method the warning disappears.
Something must be confusing the static analysis here. One can always submit this to youtrack so jetbrains devs can look at it.
Someone already reported this issue Here
(tested on v14.0.3)
This message is being shown because IntelliJ checks for method contract violations. It's a relatively new feature, read more at https://www.jetbrains.com/idea/features/annotation_java.html

trouble finding NullPointerException used try catch instead of if statement

I've been struggling to find why my if statement didnt work properly so I used a try catch block instead. This is the if statement as I had it:
//selectArtistByName returns an Artist object
if (!selectArtistByName(artist.getName()).equals(artist.getName()) ||
selectArtistByName(artist.getName())==null) {
//save data to database
}
When I ran the above, I got a NullPointerException because the method selectArtistByName was returning null as the database was empty. What I don't understand is why it didn't go in the if statement when I was getting null. So I did this and it worked:
try {
if (!selectArtistByName(artist.getName()).equals(artist.getName())) {
}
} catch (NullPointerException e) {
m_db.insert(TABLE_ARTIST, null, artistContents);
}
I'm not a Java guru but it looks like a horrible fix to me. How could I fix this.
You just need to change the order of condition in if block:
if (selectArtistByName(artist.getName()) == null ||
!selectArtistByName(artist.getName()).equals(artist.getName())) {
//save data to database
}
Do the null check first.
If that succeeds, then 2nd condition is not evaluated, and hence no NullPointerException. This is how short-circuit OR operator works. It only evaluates the 2nd expression, if 1st one evaluates to false.
If null check fails, then 2nd condition is evaluated, which wouldn't throw NPE, as it has already been confirmed by first condition.
Also, as rightly pointed out by #ruakh in comment, your condition seems to be broken. selectArtistByName sounds to be returning an Artist, which you can't compare with String.
I guess, you don't even need the 2nd condition. I would assume, selectArtistByName() method has already done the equality check for name, based on which it will return Artist. Just check that selectArtistByName method return null, that would be enough. So, you should change the if block to:
if (selectArtistByName(artist.getName()) == null) {
//save data to database
}
Just put the null condition check at the beginning to shortcut when artist is unknown:
if (selectArtistByName(artist.getName())==null || !selectArtistByName(artist.getName()).equals(artist.getName())) {
//save data to database
}
You can find more info about lazy evaluation in this other question: Does Java have lazy evaluation?

Null Pointer Exception in an If statement

Hoping you guys can figure out why im getting a null pointer exception with what I can provide, the program has several classes and method but this is the one that is breaking.
public void search(Node node, String sData, int iData)
{
if (sData.equals(node.getString()) && (iData == node.getInt()))
{
System.out.println("Nailed it");
}else if (sData.compareTo(node.stringData) < 0)
{
search(node.left, sData, iData);
}else if (sData.compareTo(node.stringData) > 0)
{
search(node.right, sData, iData);
}
}
the Node that is getting input at first is the root and then it goes left or right from there through recursion, but the line that says its erroring is the if statement up top. Cannot figure out what is wrong sData is just a standard string input when the method is called and iData is just an int thats input as well. Cannot figure it out =/ thanks for any help
You need to add the following at the top of your method:
if (node == null) return;
This would ensure that the method returns gracefully if you search for something that doesn't exist in the structure. Otherwise with your existing code, you'll encounter NullPointerExceptions when the method encounters leaf nodes.
Two possibilities: either sData or node are null; your recursive calls potentially pass null nodes, that's what I'd start with. I can't really tell more from your code, sorry.
Additionally, consider using a debugger to step through your code if you can't find the error. That usually helps with code like this.

Categories