java operator precedence with assignment - java

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.

Related

Android Studio: lint to enforce '&&' instead of '&'?

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.

Java assignment operator

The following blockquote is taken from http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-137265.html
Do not use the assignment operator in a place where it can be easily confused with the equality operator. Example:
if (c++ = d++) { // AVOID! (Java disallows)
...
}
should be written as
if ((c++ = d++) != 0) {
...
}
I am confused by the line
if ((c++ = d++) != 0) {
Any clarification on this would be appreciated.
At the very beginning of the page I can see -
This page is not being actively maintained. Links within the documentation may not work and the information itself may no longer be valid. The last revision to this document was made on April 20, 1999
if ((c++ = d++) != 0) {
//logic
}
Syntax is not even valid (Using Java6). It gives me
The left-hand side of an assignment must be a variable
You need to assign c++ to some variable.
In contrast with other languages like C, Java's scalar primitives (integers, etc.) cannot be used as booleans. In other words, 0 is in no sense either true or false. Only whether something is equal to 0 can be true or false.
They're just trying to say that the compiler requires the condition of an if statement to evaluate to a boolean value. If you know what you're doing, and decide to put actual code with side effects as the condition, you're required to make the expression evaluate to a value of type boolean.
Whereas the anti-pattern code in the example would work out in a programming language like C where boolean values are actually integers (where zero is false, and non-zero is true), the proper way to do this in Java is to actually compare the result to 0.
(c++ = d++) is an integer expression, not a boolean expression. It evaluates to whatever integer c got assigned to in the c++ = d++ assignment. Hence if (c++ = d++) { is a non starter in java.
So the comparison with 0 is what it takes to convert the integer expression to boolean.
And I think it goes without saying. Code written as follows:
if ((c++ = d++) != 0) {
is just bad coding. First, the the inner assignment within a comparison. Then the postfix operators within it. Both contribute to a block of code that is difficult to read, easy opportunities for bugs, difficult to maintain etc... Better written as follows:
c = d;
c++;
d++;
if (c == d) {
But you already knew that. :)

Why Syntax error appears on the following if condition

Hi I have a following if condition in java
if ((i%3)==0)
do some work
else if ((i%3 || i%5)==0)----syntax error appears on this line
do some work
And it is showing me following syntax error...
Multiple markers at this line
- The operator || is undefined for the argument
type(s) int, int
- Syntax error on token "OR", . expected
- i cannot be resolved or is not a field
can any one please tell me how can i fix this one ??
You can't specify multiple conditions like that. The || operator operates on boolean values only; it can't operate on numbers the way you would like them to operate. You must specify each condition individually:
else if ((i%3 == 0) || (i%5 == 0))
In English, we would say "i is a multiple of 3 or 5" and we would know what you mean. It doesn't work that way in Java. You must be more explicit. The required Java code is equivalent to "i is a multiple of 3 or i is a multiple of 5".
You have to have the comparison with every part of the condition. In this case your else if should look like this
else if (i%3 == 0 || i%5 == 0)
the || operator can only be used on bool types. i%3 is an integer.
Logical operator can only applied to boolean conditions. you are applying OR condition for two integers. If your i is 10, then i%3 = 1 and i%5 = 0. So then you are evaluating (1 || 0). If you really want to do that then you should use bitwise operator (|). Otherwise, use parenthesis which you already used in the first if part. so it will be either
else if((i%3 == 0) || (i%5 == 0))
or
else if((i%3 | i%5) == 0)
Thanks

How compilers evaluate mathematical expressions?

I was reading this question and then I made the following.
a = b + (c - (b = c)) + (a - (c = a))
I tried that in C and Java. It works with java , but not C.
Of course, it depends on how the compiler evaluate such expressions and after googling about that, I failed to find the answer.
The reason why it doesn't work in C is because C doesn't specify exactly when the c = a will occur. It can occur before or after the two other times it is referenced in that statement.
So depending on when the compiler decides to perform the assignment c = a, the value of the expression will vary. It's not defined.
i.e. If b = c is evaluated before c = a then, b will take the original value of c. If it is evaluated after, then it will take the value of a.
You can refer the java expressions document for the perfect answer.

Does Java evaluate remaining conditions after boolean result is known?

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/

Categories

Resources