I have a problem with the logic expression on my method matches1().
Problem
SonarQube is telling me there is an error:
(expectedGlobalRule == null && actual != null)
SonarQube:
Change this condition so that it does not always evaluate to
"true".
Conditions should not unconditionally evaluate to "TRUE" or to "FALSE"
I'm essentially doing this logic to avoid a NPE on my "Block to be executed".
My code
matches1()
private boolean matches1(GbRule actual, GbRule expected) {
if(actual == null && expected == null) {
return true;
} else if((expected == null && actual != null) || (expected != null && actual == null)) {
return false;
} else {
//Block to be executed
}
}
I inverted the logic in to see what SonarQube would tell me and he doesn't complain about it.
matches2()
private boolean matches2(GbRule actual, GbRule expected) {
if(actual == null && expected == null) {
return true;
} else if(expected != null && actual != null) {
//Block to be executed
} else {
return false;
}
}
Question
Do the problem is in my boolean logic or it's SonarQube that lost
his mind?
If the problem is within sonarQube, how could I resolve it?
The problem is in your logic. Let's take it piece by piece:
if(actual == null && expected == null) {
return true;
At this point if both vars are null then we're no longer in the method. So if we get any further, then at least one of them is non-null.
The viable options at this point are:
actual = null, expected = non-null
actual = non-null, expected = null
actual = non-null, expected = non-null
Now, let's look at the next bit of code:
} else if((expected == null && actual != null)
We already know that both variables can't be null, so as soon as we know expected == null, there's no need to test whether actual != null. That has already been proven by the fact that we got this far. So actual != null is always true, which is why an issue is raised.
Edit
This means that your code could be boiled down to:
private boolean matches1(GbRule actual, GbRule expected) {
if(actual == null && expected == null) {
return true;
} else if(actual == null || expected == null) {
return false;
}
//Block to be executed
}
Note that the else isn't needed & dropping it makes the code easier to read.
Even when the code is correct; seriously, it makes my eyes hurt. Thing is: it is hard to read. Such kind of nested conditions is something that one should not be writing in the first place.
If you can't avoid it; at least refactor it into something like
private boolean areActualAnedExpectedBothNull(args ...) {
return actual == null && expectedGlobalRule == null;
}
And please note; you can dramatically simply your code:
if (areActualAnedExpectedBothNull(actual, expected)) {
return true;
}
if (actual == null) {
return false;
}
if (expected == null) {
return false;
}
do your thing ...
and use such methods in your other code. And of course, you do a lot of unit testing; probably with coverage measurements; just to make sure that your tests really test all possible paths through this maze.
But as said; you better step back and think if there are ways to avoid writing such code in the first place.
The typical answer to booleans, and if/else chains in OO programming is polymorphism. So instead of asking something about its state; you turn to interfaces/abstract classes; and have different implementations of those. And then you have a factory giving you that implementation you need; and then you just call methods on that; without further need for if/else/whatever.
If you don't know what I am talking about - watch these videos; especially the second one!
The problem is with SonarQube.
See this article for more info on ignoring that issue: https://www.bsi-software.com/en/scout-blog/article/ignore-issues-on-multiple-criteria-in-sonarqube.html
You can just set it up to ignore that error within that file.
The gist of it is
Open the Settings (SonarQube General Settings or project Settings) and
select the Exclusions category. Switch to the Issues Exclusions and
scroll down to “Ignore Issues on Multiple Criteria”. Set squid:S00112
as Rule Key Pattern and **/*Activator.java as File Path Pattern.
You will need to change the rule key pattern to the pattern associated with the rule that is being violated for your code and the file pattern as the path of your .java file.
Related
I used spring boot to develop a shell project used to send email, e.g.
sendmail -from foo#bar.com -password foobar -subject "hello world" -to aaa#bbb.com
If the from and password arguments are missing, I use a default sender and password, e.g. noreply#bar.com and 123456.
So if the user passes the from argument they must also pass the password argument and vice versa. That is to say, either both are non-null, or both are null.
How do I check this elegantly?
Now my way is
if ((from != null && password == null) || (from == null && password != null)) {
throw new RuntimeException("from and password either both exist or both not exist");
}
There is a way using the ^ (XOR) operator:
if (from == null ^ password == null) {
// Use RuntimeException if you need to
throw new IllegalArgumentException("message");
}
The if condition will be true if only one variable is null.
But I think usually it's better to use two if conditions with different exception messages. You can't define what went wrong using a single condition.
if ((from == null) && (password != null)) {
throw new IllegalArgumentException("If from is null, password must be null");
}
if ((from != null) && (password == null)) {
throw new IllegalArgumentException("If from is not null, password must not be null");
}
It is more readable and is much easier to understand, and it only takes a little extra typing.
Well, it sounds like you're trying to check whether the "nullity" condition of the two is the same or not. You could use:
if ((from == null) != (password == null))
{
...
}
Or make it more explicit with helper variables:
boolean gotFrom = from != null;
boolean gotPassword = password != null;
if (gotFrom != gotPassword)
{
...
}
Personally, I prefer readable to elegant.
if (from != null && password == null) {
throw new RuntimeException("-from given without -password");
}
if (from == null && password != null) {
throw new RuntimeException("-password given without -from");
}
Put that functionality in a 2 argument method with the signature:
void assertBothNullOrBothNotNull(Object a, Object b) throws RuntimeException
This saves space in the actual method you are interested in and makes it more readable. There is nothing wrong with slightly verbose method names and there is nothing wrong with very short methods.
A Java 8 solution would be to use Objects.isNull(Object), assuming a static import:
if (isNull(from) != isNull(password)) {
throw ...;
}
For Java < 8 (or if you don't like using Objects.isNull()), you can easily write your own isNull() method.
Here is a general solution for any number of null checks
public static int nulls(Object... objs)
{
int n = 0;
for(Object obj : objs) if(obj == null) n++;
return n;
}
public static void main (String[] args) throws java.lang.Exception
{
String a = null;
String b = "";
String c = "Test";
System.out.println (" "+nulls(a,b,c));
}
Uses
// equivalent to (a==null & !(b==null|c==null) | .. | c==null & !(a==null|b==null))
if (nulls(a,b,c) == 1) { .. }
// equivalent to (a==null | b==null | c==null)
if (nulls(a,b,c) >= 1) { .. }
// equivalent to (a!=null | b!=null | c!=null)
if (nulls(a,b,c) < 3) { .. }
// equivalent to (a==null & b==null & c==null)
if (nulls(a,b,c) == 3) { .. }
// equivalent to (a!=null & b!=null & c!=null)
if (nulls(a,b,c) == 0) { .. }
Since you want to do something special (use defaults) when both sender and password are absent, handle that first.
After that, you should have both a sender and a password to send an e-mail; throw an exception if either is missing.
// use defaults if neither is provided
if ((from == null) && (password == null)) {
from = DEFAULT_SENDER;
password = DEFAULT_PASSWORD;
}
// we should have a sender and a password now
if (from == null) {
throw new MissingSenderException();
}
if (password == null) {
throw new MissingPasswordException();
}
An added benefit is that, should either of your defaults be null, that will be detected as well.
Having said that, in general I think that use of XOR should be permissible when that is the operator you need. It is a part of the language, not just some trick that works because of an arcane compiler-bug.
I once had a cow-orker who found the ternary operator too confusing to use...
I would like to suggest another alternative which is how I would actually write this piece of code:
if( from != null )
{
if( password == null )
error( "password required for " + from );
}
else
{
if( password != null )
warn( "the given password will not be used" );
}
To me this seems to be the most natural way to express this condition which makes it easy to understand for somebody who might have to read it in the future. It also allows you to give more helpful diagnostic messages and treat the unnecessary password as less serious and it makes it easy to modify which is rather likely for such a condition. I.e. you may find out that giving a password as a command line argument is not the best idea and may want allow reading the password from standard input optionally if the argument is missing. Or you may want to silently ignore the superfluous password argument. Changes like these would not require you to rewrite the whole thing.
Besides that it executes only the minimum number of comparisons, so it's not more expensive than the more "elegant" alternatives. Although performance is very unlikely a problem here because starting a new process is already much more expensive than a extra null check.
I think a correct way to handle this is to consider three situations: both 'from' and 'password' are provided, neither are provided, a mix of the two are provided.
if(from != null && password != null){
//use the provided values
} else if(from == null && password == null){
//both values are null use the default values
} else{
//throw an exception because the input is not correct.
}
It sounds like the original question wants to break the flow if it is incorrect input, but then they will have to repeat some of the logic later. Perhaps a good throw statement might be:
throw new IllegalArgumentException("form of " + form +
" cannot be used with a "
+ (password==null?"null":"not null") +
" password. Either provide a value for both, or no value for both"
);
Here's a relatively straight-forward way that does not involve any Xor og lengthy ifs. It does however require you to be slightly more verbose, but on the upside, you can use the custom Exceptions I suggested to get a more meaningful error message.
private void validatePasswordExists(Parameters params) {
if (!params.hasKey("password")){
throw new PasswordMissingException("Password missing");
}
}
private void validateFromExists(Parameters params) {
if (!params.hasKey("from")){
throw new FromEmailMissingException("From-email missing");
}
}
private void validateParams(Parameters params) {
if (params.hasKey("from") || params.hasKey("password")){
validateFromExists(params);
validatePasswordExists(params);
}
}
Nobody seems to have mentioned the ternary operator:
if (a==null? b!=null:b==null)
Works nicely for checking this particular condition, but doesn't generalize well past two variables.
As I see your intentions, there is no need to always check both exclusive nullities but to check if password is null if and only if from is not null. You can ignore the given password argument and use your own default if from is null.
Written in pseudo must be like this:
if (from == null) { // form is null, ignore given password here
// use your own defaults
} else if (password == null) { // form is given but password is not
// throw exception
} else { // both arguments are given
// use given arguments
}
I'm surprised nobody mentioned the simple solution of making from and password fields of a class and passing a reference to an instance of that class:
class Account {
final String name, password;
Account(String name, String password) {
this.name = Objects.requireNonNull(name, "name");
this.password = Objects.requireNonNull(password, "password");
}
}
// the code that requires an account
Account from;
// do stuff
Here from could be null or non-null and if it's non-null, both its fields have non-null values.
One advantage of this approach is that the error of making one field but not the other field null gets triggered where the account is initially obtained, not when the code using the account runs. By the time the code using the account is executed, it's impossible for the data to be invalid.
Another advantage to this approach is more readable as it provides more semantic information. Also, it's likely that you require the name and password together in other places so the cost of defining an additional class amortizes over multiple usages.
if ((from == null) == (password == null)){ //if both are true or both are false
}
(Source: Intellij IDEA)
I am using Talend to filter out some rows from an excel file and they don't allow block statements. Everything has to be simple logic or using the ternary operator. So the problem is that the code/logic I need will be used across every cell in the column, BUT some of the cells are null, some are Strings and the rest are Strings that represent integers.
My logic needs to be this:
Return true if and only if PlanName == null || PlanName == 0 but as you can tell, it will fail when it tries to run this on a cell that contains the null or the cell that contains a String that isn't a number.
Is it possible to have this logic in java without the try-catch or block statements? This is what I have right now:
input_row.PlanName == null || Integer.parseInt(input_row.PlanName) == 0
Thanks!
Edit: Basically, I just need to write logic that does this:
Return true if input_row.PlanName == null OR if input_row.PlanName == 0
This needs to be done without using block-statements or try-catches because I am using Talend. So I can only use logical operators like && and || and I can use ternary operators as well.
In your situation, i'll go for routines : reusable bunch of code, handy for this kind of rules that would be hard to implement without if/else etc.
You can create two Routines in Talend, with static methods that you would be able to use in a tMap or a tJavaRow.
First Routine to know if your plan is a numeric or not :
public static boolean isNumeric(String strNum) {
if (strNum == null) {
return false;
}
try {
double d = Double.parseDouble(strNum);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
Then another routine like :
public static boolean correctPlanName(String planName) {
if(Relational.ISNULL(planName)){
return false;
}
else{
if(!isNumeric(planName)){
return false;
}
else {
return true;
}
}
}
Then you call Routines.correctPlanName(input_row.planName) in tMap/tJavaRow.
It should do the trick.
You can use a regular expression to check if the String only contains digits, then check if num == 0.
input_row.PlanName == null || (input_row.PlanName != null && input_row.PlanName.matches("\\d+") && Integer.parseInt(input_row.PlanName) == 0)
Edit: Probably overkill but to cover other cases e.g. floating point types, numbers prefixed with +/-, you could also do:
input_row.PlanName != null && input_row.PlanName.matches("[-+]?\\d*\\.?\\d+") && Double.parseDouble(input_row.PlanName) == 0)
I have a situation in my code where I make about 5 chained get calls, and any of those get calls could return a null value. I wish it didn't have to be that way, but that's just how the service I'm consuming returns the object I request, so I have to deal with it.
Originally, my code looked something like this:
String firstDomain = book.getBookImages().getDomains().getDefaults().getDomain().get(0);
Unfortunately, that line is prone to null pointers and arraylist out of bounds exceptions. I know I'm going to have to check for null pointers, but I'm trying to decide
A. The most efficient code to do so
and
B. The best looking code to do so
One option is to assign a ton of references and then check for nulls. Something like this:
BookImages bImages = book.getBookImages();
Domains domains = null;
Defaults defaults = null;
List<String> domain = null;
String firstDomain = null;
if (bImages != null) {
domains = bImages.getDomains();
if (domains != null) {
defaults = domains.getDefaults();
if (defaults != null) {
domain = defaults.getDomain();
if (domain != null && domain.size() > 0) {
firstDomain = domain.get(0);
}
}
}
}
if (firstDomain == null) {
throw new IncompleteBookException("The book was incompletely attributed.");
}
I think that's pretty efficient, but it bothers me how many lines it is. It more than doubles the length of the method it is a part of.
This is the other alternative I can think of:
if (book.getBookImages() == null || book.getBookImages().getDomains() == null || book.getBookImages().getDomains().getDefaults() == null || book.getBookImages().getDomains().getDefaults().getDomain() == null || book.getBookImages().getDomains().getDefaults().getDomain().size() < 1 || book.getBookImages().getDomains().getDefaults().getDomain().get(0) == null) {
throw new IncompleteBookException("The book was incompletely attributed.");
}
I like the fact that that's only three lines, even if one is pretty darn ridiculous, but I'm not sure if Java's runtime or compiler would optimize away those repetitive method calls.
I'm also open to other, better solutions. Does anyone know if one or the other of those options would perform better than the other, or is this such a micro-optimization that it's foolish to even bother thinking about it, and I should just use whichever looks nicer to me? I may have to do this many times for different things.
To follow your second approach, you can apply this:
if ((bImages=book.getBookImages()) == null
|| (domains=bImages.getDomains()) == null
|| (defaults=domains.getDefaults()) == null
|| (domain=defaults.getDomain()) == null
|| domain.size() < 1
|| (firstDomain=domain.get(0)) == null) {
throw new IncompleteBookException("The book was incompletely attributed.");
} else {
//here you can use the firstDomain variable, that is set with the correct value
}
This is better because you avoid multiple (useless) identical calls, and you already set the correct value in the variable firstDomain (of course, only if there is nothing null and so on...)
As Szymon pointed out you should not call same method twice.
To make your original solution slightly more readable by combining all your nested null checks into one:
BookImages bImages = null;
Domains domains = null;
Defaults defaults = null;
List<String> domain = null;
String firstDomain = null;
if ((bImages = book.getBookImages()) != null
&& (domains = bImages.getDomains()) != null
&& (defaults = domains.getDefaults()) != null
&& (domain = defaults.getDomain() != null
&& domain.size() > 0) {
firstDomain = domain.get(0);
}
You should not worry about the length of the code too much if the longer code is correct and shorter incorrect. The goal of programming is not writing the shortest possible code (with the exception of some competitions, etc).
Your first (longer) way is correct, even if a bit longish.
The second way will make repeated calls to the same method. This is something you probably want to avoid - it may have undesirable effects and is worse for performance.
Try using a boolean method; they tend to make logic a lot simpler and much more legible; for example, I would do this:
public boolean isCompletelyAttributed(BookImages bImages) {
if (bImages == null) return false;
if (bImages.getDomains() == null) return false;
if (bImages.getDomains().getDefaults() == null) return false;
if (bImages.getDomains().getDefaults().getDomains() == null) return false;
return bImages.getDomains().getDefaults.getDomains.size() > 0;
}
Then you call
if (!isCompletelyAttributed(book.getImages())) {
throw new IncompleteBookException("The book was incompletely attributed.");
}
I also recommend that you use Nicola or kiruwka's solution in your boolean method. I was not aware that you could reassign variables while doing logic on them, but that appears to be an elegant solution.
Here's a short-ish way to do it. But hey, I don't know the specifics of what you're building and whether this works for you.
try {
String firstDomain = book.getBookImages().getDomains().getDefaults().getDomain().get(0);
// operate on firstDomain
} catch (NullPointerException e) {
throw new IncompleteBookException("The book was incompletely attributed.");
} catch (IndexOutOfBoundsException e) {
throw new IncompleteBookException("The book was incompletely attributed.");
}
I've heard that people are concerned with the performance of something like this, because the VM will have to fill in a stack trace for the NullPointerException. In this case, you'll already be doing a comparable operation for the IncompleteBookException anyway.
This question already has answers here:
Avoiding NullPointerException in Java
(66 answers)
Closed 9 years ago.
What is the best way to avoid multiple if blocks which is used for null checks in Java?
The following is my sample code. Which one is the most optimized way?
if (address!=null} {
if (firstName!=null) {
if (lastName!=null) {
}
}
}
Use &&. && is logical and. && combines two values and returns a boolean which is true if and only if both of its operands are true
if(address!=null && firstName!=null && lastName!=null)
{
}
For instance
boolean b;
b = 3 > 2 && 5 < 7; // b is true
b = 2 > 3 && 5 < 7; // b is now false
if loop is a wrong word. You should say if statements As in you case you can use OR (||) or AND (&&)statement like this
if(address!=null && firstName!=null && lastName!=null)
{
}
Try AND(&&) if you want to pass all checks or intead of nested if statements and try OR(||) for non nested like else if or simply say if you want to pass anyone of your condition But
if all of these are Strings then you should try like this
"yourValue".equals(stringValue)This will skip the null check.
Use and operator (&&)
if(address!=null && firstName!=null && lastName!=null)
{
//DoSomething here
}
And I suggest you to see Short circuit evaluation
there are no if LOOPS
boolean complete = address != null && firstName != null && lastName != null;
if (complete)
{
}
What about:
public boolean notNulls(Object ... args) {
for(Object arg : args)
if (arg == null) return false;
return true;
}
Use:
if (notNulls(address, firstName, lastName)) {
// do something
}
As others point out, a logical and (&&) is probably the best way to consolidate your logic. An && operation will only evaluate to true if both sides evaluate to true.
if (address != null && firstName != null && lastName != null) {
// Whatever you want to do with that...
} else {
// Whatever you want to do with bad input
}
For the sake of diversity, you could also use a try-catch approach. In Java, a NullPointerException will be thrown if you try to call a method on a null value, which you can catch and handle.
try {
// Whatever you want to do with that...
} catch (NullPointerException npe) {
// Whatever you want to do with bad input
}
This approach can be helpful if you've got a really big set of inputs that might be null, although in general I wouldn't advocate it. (The problem with the second approach is that if you call some other method from the try part that triggers a NullPointerException, it will end up in the catch block here, even though it may be totally unrelated to these inputs - i.e. you could make it hard for yourself to spot a bug in a different part of your program.)
I use PMD to check my code. It gives me very useful hints in most cases, but I can't figure out what could be improved in the following scenario.
The original code looks something like this:
if ((getSomething() != null && getSomethingElse() != null)
|| (getSomething() == null && getSomethingElse() == null))
{
...
}
PMD tells me:
Sometimes two 'if' statements can be consolidated by separating their
conditions with a boolean short-circuit operator.
For simplicity, let's just use a and b as boolean variables. Then this piece of code looks like this:
if ((!a && !b) || (a && b))
This can be transformed to one of the following:
if ((!a || b) && (a || !b))
if (!(a^b))
and finally
if (a==b)
So I simplified my code to
if ((getSomething() == null) == (getSomethingElse() == null))
However, PMD keeps complaining (in fact about all three versions). Is this a false positive or is there a better way of writing the if-condition?
The problem was something different. The if-statement was the only code inside another if (the code comes from a validation-method):
if (...)
{
...
}
else if (...)
{
...
}
else if (...)
{
if ((getSomething() == null) == (getSomethingElse() == null))
{
...
}
}
What the PMD-message means, is that I could combine the conditions of the last else-if and the inner if-clause:
if (...)
{
...
}
else if (...)
{
...
}
else if (... && ((getSomething() == null) == (getSomethingElse() == null)))
{
...
}
However, I'm not sure, if I'll do this, because the original version seems much clearer to understand.
if ((a != null) && (b != null) && (a==b))
..although personally, I'd do the null checking prior to this if statement so I could handle the a == null and b == null cases individually
The issue is that large blocks of conditionals are difficult to reason about.
OTOH, not every warning PMD emits needs to be paid attention to--consider the ROI. Is it worth refactoring or restructuring to make it cleaner? Can the same functionality be handled in a different way?
If it's not worth it, don't bother.