Is there an option in Android Studio linter settings to make sure any occurrence of the boolean '&' operator causes an error and only allowing the '&&' operator (while still allowing the & operator for bit-wise operations on numbers)?
TL;DR: As you probably know, in Java the '&' operator evaluates both operands before it performs the AND operation, while the '&&' operator stops evaluating operands at the first operand evaluating to false.
I personally find this distinction both confusing and pointless. With the '&&' operator you can do things like:
if (a != null && fn (a)) { ... }
meaning that fn should never be called with a value of null. If I accidentally write:
if (a != null & fn (a)) { ... }
the whole test is completely meaningless. I want to ensure this kind of typo can never occur. A linter rule would be the perfect way to enforce this.
The linter rule should distinguish between the types of the operands. When & is used with numbers, its meaning is a bit-wise and operator. I do not want to disallow this, of course, as it's quite useful. Moreover, the OR operators | and || behave in a similar way, and I want to disallow | for booleans while allowing it for numerical operations. So basically:
int a = (3 & 4); // OK
boolean b = (true && false); // OK
boolean c = (true & false); // linter error, hopefully
int d = (5 | 7); // OK
boolean e = (true || false); // OK
boolean f = (true | false); // linter error, hopefully
Is there an option in Android Studio linter settings to make sure any occurrence of the boolean '&' operator causes an error and only allowing the '&&' operator?
The short answer is "no."
You can always write your own lint rules (see here for a sample), but this is not a default option in IntelliJ.
This isn't a matter of "personal taste" either. & and && both exist for a reason, just like | and ||.
When it comes to boolean statements, you are correct on the difference. However, the fundamental difference is that & is a bitwise "and" while && is a logical "and."
There are plenty of situations in which someone might want a bitwise "and," so making its use a blanket error is not a good idea. The most common use case is using it as a mask.
For example, MotionEvent's getAction() method returns an integer with both the pointer index and the action. To get the action, you need to mask the return value like so: getAction() & ACTION_MASK.
Related
This question already has answers here:
Java logical operator short-circuiting
(10 answers)
Closed 5 months ago.
When we're using an if-conditional, we specify the condition in a boolean expression such as following :
if(boolean expression).
If I have two variables in a boolean expression, such as (bagWeight > WEIGHT_LIMIT), does the order of the two variables in which they appear matter? In other words, can I swap those two variables' places such as following? (WEIGHT_LIMIT < bagWeight). Notice it would still be bag weight is less than weight limit, but I just switch the order of which one appears first in the boolean expression. AND Does it depend on which one becomes a subject, like one that gets focused on and evaluated? (In this case, we're trying to figure out if the bag weight is heavier than the limit or not. So the bag weight gets evaluated according to something.. I would call it a subject.)
Eclipse doesn't scream at me that it's wrong, and intuitively it makes sense, but somehow it just bothers me whether there's a more common programming practice or not. So my questions were, can I swap the two variables' places and would not matter? and does it depend on the context of which being a subject? and which is a more common programming practice?
You can freely change the order of the two variables as you prefer. Eclipse (or the compiler) doesn't care, it just evaluates the expression and returns a value, either true of false.
can I swap those two variables' places such as following? (WEIGHT_LIMIT < bagWeight)
Yes, it will still work exactly the same.
Order only comes in to play when using short circuit operates such as || or &&.
examples:
if (boolean1 || boolean2)
In this case, boolean1 will be evaluated first. If it evaluates to true, then boolean2 will not be evaluated, since the first one meets the criteria of the if statement.
if (boolean1 && boolean2)
In this case if boolean1 is evaluates to false, then boolean2 will never be evaluated because the fact that boolean1 is false means that even if boolean2 was true, the condition of the if statement would never be satisfied.
Hope that helps.
The order that Java evaluates && and || is not so important if everything is already evaluated into variables as in your example. If these where method calls instead then the second part of the "if" will not be called unless necessary. Examples of when the myMethod() would not be evaluated at all.
if (true || myMethod())
or
if (false && myMethod())
That's why you might see statements similar to this in actual code.
String myStr = null;
if (myStr != null && myStr.trim().size() > 0)
If Java were to evaluate the second part then you would get a NullPointerException when myStr is null. The fact that Java will bypass the second part keeps that from happening.
The order of the operands doesn't matter in your specific case. Since the if statement is comparing two values, the two values must be evaluated. However, there are some cases when order does matter:
|| and &&
|| and && are shorthand logic operators. The second operand of || will not be evaluated if the first is true. The second operand of && will not be evaluated if the first is false.
++ and --
These can yield different results:
if (i++ > i)
if (i < i++)
In the first line, i is evaluated after the increment is done, so the first operand is 1 less than the second.
In the second line, i is evaluated first, which evaluates to i, then i++, which evaluates to i as well.
I would be grateful if someone could please explain why the following is occuring. Thanks a lot.
boolean b = true;
// Compiles OK.
// The LHS "assignment operand" requires no ()parentheses.
if (b=true || b==true);
// Reverse the ||'s operands, and now the code doesn't compile.
if (b==true || b=true);
// Add () around the RHS "assignment operand", and the code now compiles OK.
if (b==true || (b=true));
Edit -
BTW, the compilation error for code line #2 is: "unexpected type", and occurs where the short-circuit OR operator is located:
if (b==true || b=true);
// ^ "unexpected type" compilation error occurs here.
Edit 2 -
Please note that the code fragments found in this question are examples of "highly artificial Java coding", and consequently would not be seen in professionally written code.
Edit 3 -
I'm new to this incredibly useful website, and I've just learnt how to make and upload screenshots of Java's compilation messages. The following image replicates the information that I provided in my first "Edit" above. It shows the compilation error for example code line #2.
The assignment operator = has lower precedence than the logical or operator || so that you can use the logical operator in an assignment without extra pairs of parentheses. That is, you would want to be able to write
a = b || c;
instead of being forced to write a = (b || c).
Unfortunately, if we work with operator precedence only, this rule also applies to the left hand side of the expression. a || b = c must be parsed as
(a || b) = c;
even if what you intended was a || (b = c).
Assignments have the lowest precedence in Java. Thus, your first two expressions are equivalent to:
if ( b = (true || b==true) );
if ( (b==true || b) = true );
The second one doesn't compile because the expression (b==true || b) is not an lValue (something that can be assigned to).
If you add parentheses, you do the assignment before the OR, and everything works.
Using operator precedence (http://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html) we have this (I added parentheses to indicate precedence):
if (b=(true || (b==true))), b will be assigned to expression and returns boolean, so it fits for condition;
if (((b==true) || b)=true), left side doesn't fit for assignment operator (as it is expression rather than variable);
if (((b==true) || (b=true))), boolean comprates to boolean with OR, right boolean is boolean because b is variable and = returns the assigned value.
I read somewhere that Java is supposed to 'short-circuit' once the If statement has reached a True boolean. However, I am currently experiencing a null pointer exception in the following code (which I have simplified for the purpose of this question):
currentFragment.setTag(HOME);
if( !currentFragment.getTag().equals(PROFILE) |
( currentFragment.getArguments() != null &
currentFragment.getArguments().getInt("authorId") != userId) ) { }
Android developers will know that setTag() is not a real method, but in my actual code I have made sure that currentFragment.getTag() != PROFILE by error logging. However, when this code runs, it causes a null point exception at
currentFragment.getArguments().getInt("authorId") != userId
It should short-circuit at the very first condition before the | (OR) operator. Failing that, the next line should make sure the getArguments() != null, so why is it going all the way to the final condition? Can any explain the inner workings of what is going on here. Thanks.
You're using & instead of &&. The former is bitwise AND and will evaluate both sides always. The latter stands for logical AND and will do short-circuit conditional evaluation.
More info: Java Tutorials: Operators
Solution for your current problem: use logical AND && instead of bitwise AND &. Similar for your bitwise OR |.
if( !currentFragment.getTag().equals(PROFILE) ||
( currentFragment.getArguments() != null &&
currentFragment.getArguments().getInt("authorId") != userId) ) { }
& - Bitwise operator for AND
&& - Logical AND (AND gate of Digital logic)
The logical AND && performs Short-Circuit
"&" and "|" have two meanings, depending on their operands. Applied to integers, they are bitwise AND and OR respectively. Applied to boolean operands, they are the non-short-circuit versions of logical AND and OR.
People often forget their logical operator meaning, because almost always we use the short-cicuit equivalents, "&&" and "||".
Rarely I bump into & and | logic operators in other's codes instead of || and &&. I made a quick research because I never used them and didn't know what is it for.
A && B means if A is false, B won't be evaluated and it will return false.
A & B means if A is false, B will be evaluated even if the form will return false as well.
Of course it is the same game with | and ||.
My question is: does it make sense anyways to evaluate the second member if the first determine the evaluation? I can imagine a code where the second member does something super important logic in clode and so it should be evaluated, but I suspect it is bad practice. Is it enough to make | and & exist?
from a comment, to make it more clear: I have the feeling that the program is not optimal and working well or better to say: designed well if all of the logical members HAS to be evaluated.
You forgot about bitwise operations
The bitwise & operator performs a bitwise AND operation.
The bitwise | operator performs a bitwise inclusive OR operation.
But here you can find example when unconditional AND operator is better:
What are the cases in which it is better to use unconditional AND (& instead of &&)
The single & and | are not logical operators, they're bitwise and logical operators.
You can use the | and & operators as you said above. Some static code analyzers will warn you because it might mask a possible problem. In those cases where you really want both conditions evaluated, you can do something like:
boolean cond1=cond1();
boolean cond2=cond2();
boolean myCond=cond1 && cond2;
if you just use
boolean myCond=cond1()&cond2();
someone is bound to "correct" it for you.
So yes, there are places where you would use & and |, but most likely it's not a good idea and you can get around it for the sake of clarity.
Imagine if B was a function that you wanted to execute all the time then it would be useful.
I think that might be quite good example:
if (initializeConnectionA() & initializeConnectionB() & initializeConnectionC()) {
performOperation();
} else {
logger.warn("Not all modules are working properly");
}
Where methods initializeConnection connects to i.e. some external servers that might not all be working. You might not require to initialize them all but you want to be warned if some of them are not working.
Of course it might not be the clearest solution for this problem, but this is example where & operator might be useful.
That is, if I have a statement that evaluates multiple conditions, in say a 'or' statement like so..
if(isVeryLikely() || isSomewhatLikely() || isHardlyLikely())
{
...
}
In the case that isVeryLikely() returns true at runtime, will isSomewhatLikely() and isHardlyLikely() execute? How about if instead of methods they were static booleans?
The || and && operators are short-circuiting.
true || willNeverExecute();
false && willNeverExecute();
The first thing that you need to note is that Java conditional statements can only take boolean, unlike other languages like C/C++ where any non-zero value will evaluate to true.
That being said, there are 2 types of operators, the first is known as the shor-circuit types:
&& and ||
while the other are the NON-short-circuit types:
& and |
For the Short-Circuit types, once a logical output can be found as an answer to the expression, the rest of the statement will be dumped. For the NON-Short-Circuit types, they will continue to evaluate all conditions.
With this in mind, what you have:
if(isVeryLikely() || isSomewhatLikely() || isHardlyLikely())
{
...
}
Java will:
First check if isVeryLikely()
returns true. If true, then it will
not continue further.
If isVeryLikely() returns false,
then invoke isSomewhatLikely() to
see if it returns true. If true,
nothing else if evaluated. If false,
goto 3.
isHardlyLikely() is invoked. If
true, entire expression is true,
otherwise false, entire
expression is false.
The entire concept you're asking about is "How does Java evaluate Logical Expressions." Good question :)
Hope it helps! Cheers!
No, java uses short-circuit evaluation on expressions using || and &&. See here for more info.
Because the || is short circuiting, the statement will be evaluated to true as soon as it hits the first true condition, regardless of whether or not the operands are static.
In short, no the two other functions will not be evaluated if the first returns true.
The short answer is, it will evaluate until has enough to conclude whether it is T/F.
There is something called boolean short-circuiting. Essentially it will try and evaluate only what it needs to (if you use the && or || operators) and the leave. You can take advantage of this in a few ways:
(a() || b())
If b() would throw an exception, if a() is true, then it would not even try and check the b(). A type of chain-checking mechanism.
If the latter evaluations are resource consuming, you can move them to the end of the evaluation (eg. b() takes 10 times longer)
If the most likely path can be determined by a certain clause, put them first. This would also speed up execution.
As an update for Kotlin users, you can use 'or' operator in Kotlin std library in order to check all the expressions in the if statement and not performing a short-circuit.
In the expression presented in the initial question the code in Kotlin should be:
if(isVeryLikely() or isSomewhatLikely() or isHardlyLikely()) {
...
}
Whether for boolean expression specified in the questions are static booleans, or they are methods returning a boolean value, in both the cases - expression evaluation will start from the left and conditions will be evaluated one-by-one. The first condition which gives a value true will short-circuit the evaluation. It will directly give the result as true with the remaining conditions not being evaluated. This is how ||(OR) works in Java using the concept of short-circuit evaluation.
If you want to understand more about short-circuits in general you can refer an article I have written on my blog - http://www.javabrahman.com/programming-principles/short-circuiting-or-short-circuits-in-boolean-evaluations-in-programming-and-java/