Getting confused with == and = in "if" statement - java

I know that we cant use assignment operator in if statements in java as we use in any other few languages.
that is
int a;
if(a = 1) { }
will give a compilation error.
but the following code works fine, how?
boolean b;
if(b = true) { }
EDIT : Is this the exception to rule that assignment cant be used in if statement.

Because the "result" of an assignment is the value assigned... so it's still a boolean expression in the second case. if expressions require the condition to be a boolean expression, which is satisfied by the second but not the first. Effectively, your two snippets are:
int a;
a = 1;
if (a) { }
and
boolean b;
b = true;
if (b) { }
Is it clear from that expansion that the second version will compile but not the first?
This is one reason not to do comparisons with true and false directly. So I would always just write if (b) instead of if (b == true) and if (!b) instead of if (b == false). You still get into problems with if (b == c) when b and c are boolean variables, admittedly - a typo there can cause an issue. I can't say it's ever happened to me though.
EDIT: Responding to your edit - assignments of all kinds can be used in if statements - and while loops etc, so long as the overall condition expression is boolean. For example, you might have:
String line;
while ((line = reader.readLine()) != null)
{
// Do something with a line
}
While I usually avoid side-effects in conditions, this particular idiom is often useful for the example shown above, or using InputStream.read. Basically it's "while the value I read is useful, use it."

For if you need an expression that evaluates to boolean. b = true evalueates to boolean but a = 1 evaluates to int as assignments always evaluate to the assigned values.

The reason the second code works okay is because it is assigning 'b' the value of true, and then comparing to see if b is true or false. The reason you can do this is because you can do assignment operators inside an if statement, AND you can compare against a boolean by itself. It would be the same as doing if(true).

In java, you don't have implicit casting. So non-boolean values or not automatically transformed to booleans.
In the first case, the result of the statements is an int, which is non-boolean, which will not work. The last case, the result is boolean, which can be evaluated in an if-statement.

The rule is not that "assignment can't be used in an if statement", but that "the condition in an if statement must be of type boolean". An assignment expression produces a value of the type being assigned, so Java only permits assignment in an if statement if you're assigning a boolean value.
This is a good reason why the style if (foo == true) should be avoided, and instead simply write if (foo).

Related

Null check + dereference on the same line

Are there any dangers in checking for null and dereferencing on the same line?
If myObj is in fact null, how would this code behave?
Are there differences in how different languages handle situations like these (ie C# vs Java)
For example, something like below
if(myObj != null && myObj.someProp == "Test")
{
//...
}
&& is short-circuiting so if myObj is indeed null then the second condition will never be evaluated.
This behaviour is the same for both C# and Java.
In your example the if condition expect a boolean value that is provided by the boolean operation myObj != null && myObj.someProp == "Test".
When using the && operator the left operand is checked first. If its value equals true then the right operand is checked as it's not possible to know its state in advance. But if its value equals false then no need to check the right operand as no matter the right condition state will be, the whole operation will result to false.
This is why it's safe.
But when using the & operator both operands are always checked. Your example would look as follows with the & operator:
if(myObj != null & myObj.someProp == "Test")
{
//...
}
Doing so, when myObj variable is equals to null then the code above will fail. In this case your code won't be safe.
I hope this helps;

Weird ternary nullpointer [duplicate]

I tripped across a really strange NullPointerException the other day caused by an unexpected type-cast in the ternary operator. Given this (useless exemplary) function:
Integer getNumber() {
return null;
}
I was expecting the following two code segments to be exactly identical after compilation:
Integer number;
if (condition) {
number = getNumber();
} else {
number = 0;
}
vs.
Integer number = (condition) ? getNumber() : 0;
.
Turns out, if condition is true, the if-statement works fine, while the ternary opration in the second code segment throws a NullPointerException. It seems as though the ternary operation has decided to type-cast both choices to int before auto-boxing the result back into an Integer!?! In fact, if I explicitly cast the 0 to Integer, the exception goes away. In other words:
Integer number = (condition) ? getNumber() : 0;
is not the same as:
Integer number = (condition) ? getNumber() : (Integer) 0;
.
So, it seems that there is a byte-code difference between the ternary operator and an equivalent if-else-statement (something I didn't expect). Which raises three questions: Why is there a difference? Is this a bug in the ternary implementation or is there a reason for the type cast? Given there is a difference, is the ternary operation more or less performant than an equivalent if-statement (I know, the difference can't be huge, but still)?
According to JLS: -
The type of a conditional expression is determined as follows:
If the second and third operands have the same type (which may be the null type), then that is the type of the conditional
expression.
If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion
(ยง5.1.7) to T, then the type of the conditional expression is T.
The problem is that:
Integer number = (condition) ? getNumber() : 0;
Forces an unboxing and reboxing of the result of getNumber(). This is because the false part of the ternary (0) is an integer, so it tries to convert the result of getNumber() to an int. Whereas the following does not:
Integer number = (condition) ? getNumber() : (Integer) 0;
This is not a bug, just the way Java chose to do things.
This is how it is supposed to work. The ternary operator is not meant to be equivalent to a regular if statement. The bodies of if and else are statements, while the parts following ? and : are expressions, that are required to evaluate to the same type.
Put another way: a = b ? c : d is not supposed to be equivalent to if (b) a = c; else a = d;. Instead, b ? c : d is an expression on its own, and the assignment of its result to a won't affect the outcome.

Why don't Java logical operators && and || work with arrays?

I am effectively trying to write a multiple-bit if-statement in binary. If val is true, I would like to return the correct value of x. However, if val is false, I would like to return all values of the array to be false.
This is effectively the same as checking all values within the array against the value of val. Why doesn't this work?
boolean[] ifStatement(bit0, bit1, bit2, bit3, val) {
boolean[] x = {bit0, bit1, bit2, bit3};
return (x && val);
}
In response to comments asking what I mean by the question, the following is a representation using an 8-bit AND gate in the program Logisim:
I am also aware that it is very easy to do the same thing using a for statement. My question is why is the example code not possible?
Thanks in advance.
The short answer is no. You have check each item. It'd be kind of nice if it did work, but there you have it.
There are, however, special classes like BitSet that provide special functionality for big collections of booleans. You might find one of these useful. Typically not worth the effort for short numbers of booleans, though.
boolean[] x = {bit0, bit1, bit2, bit3};
return (x && val);
Why doesn't this work?
Your proposed meaning of that expression matches the semantics of the standard map higher-order function in the FP paradigm. Interestingly enough, I am not aware of any actual FP language which would have its AND operator overloaded to mean map((applyPartial(AND, val), coll) when one of its operands is a collection.
But, constraining the discussion to Java, such a feature would be deeply incongruent with everything else in it. It would make a logical operator suddenly behave like a batch collection operator; there is nothing even remotely close to that in Java, which is meant to be as unsurprising to beginners as possible, and especially so to people already familiar with C.
BTW you should have at least picked & because && has short-circuiting semantics, something which makes no sense in your proposal.
An array is a type all its own, not a boolean. So you can't use logical operators on an array type.
From your question description, it sounds like you just want to check every value in the array against some baseline boolean. You can do that with a loop over all elements in the array, and if any of don't match up to the baseline, return false.
public boolean ifStatement(boolean base, boolean... values) {
for(boolean value : values) {
if(!(value && base)) {
return false;
}
}
return true;
}
EDIT: After your diagram explained a few things, it seems that a boolean array is the wrong data structure. Why not work with a byte directly? (8 bits = 1 byte)
public byte ifStatement(boolean val, byte value) {
return val ? value : (byte) 0x00;
}
You're either returning value or nothing in your example, so I believe that this would work better.
This doesn't work because the Java compiler doesn't interpret your wishes but adheres to its specification.
And the boolean operators only work with, well, booleans. Arrays of booleans aren't booleans.
Actually you don't need for loop / bitwise operators:
boolean []ifStatement(boolean b1, boolean b2, boolean b3, boolean b4, boolean val) {
if (!val) {
boolean []result = {false, false, false, false};
return result;
} else {
boolean []result = {b1, b2, b3, b4};
return result;
}
}

What is the point of == true in conditionals?

I'm learning C++ and java and I've noticed how if you have a conditional, whatever code follows will be executed if the condition is true, even if you don't explicitly write == true
Consider the following very simple C++ code:
bool c_plus_plus_is_cool(){
return true;
}
int main(){
if (c_plus_plus_is_cool()) {
cout << "C++ is cool!";
}
return 0;
}
Q: What is the difference between
if (c_plus_plus_is_cool())
and if (c_plus_plus_is_cool() == true) ?
And is this also the case in other languages (like Java (where I've been writing ==true all this time...)) ?
The == operator returns a boolean.
If you already have a boolean, == true will be no different from the original boolean; there is no point in writing it.
Similarly, use the ! operator instead of == false.
One exception to this is C# nullable booleans, where == true will be false for null.
Both C++ and Java have the same behaviour in this point and in both languages the == true is just redundant noise.
If you use the verbose syntax in Java so far then this is your own private style. Even in Java this is not the commonly used and accepted/recommended style.
There is actually no difference other than syntactical bloat brought by == true.
In C/C++ and pretty much every language, if and while encapsulate blocks of code that will only be executed if a condition is true. Explicitly putting an == true into your condition statement is redundant but some programmers prefer it; it's basically a style choice and will not affect the behaviour or speed of your program.
They both are same. The language implements the conditions as follows:
When it encounters the if statement, please check whether the condition is true.
Now, when we say this, it obviously allows you to do == , which
the compiler/interpreter will deal it by saying, are the data types or value
equal? If yes then proceed further.
Refer the flowchart
The piece of code:
bool c_plus_plus_is_cool(){
return true;
}
int main(){
if (c_plus_plus_is_cool()) {
cout << "C++ is cool!";
}
return 0;
}
is same as:
int main(){
if (c_plus_plus_is_cool() == true) {
cout << "C++ is cool!";
}
return 0;
}
No difference when == true is in if or while (or something similar like for or ternary operator), especially if the left value is already of type bool, and in your case it is.
If you need to explicitly convert a value to bool, plain explicit conversion (bool(expr)) looks much better.
THE ONLY case when that strange comparison is reasonable is when the value on the left of == belongs to a class that has a comparison operator taking bool as a second argument (though that generally means bad design:)). But it is not the case, so, to my mind, such coding convention is absolutely useless and rather ugly.
The second one is a bad habit that will give wrong answers in other contexts:
int f() {
return 3;
}
if (f() == true)
std::cout << "Won't get here\n";
if (f())
std::cout << "Will get here\n";

Java Equivalent to iif function

the question is simple, there is a functional equivalent of the famous iif in java?
For example:
IIf (vData = "S", True, False)
Thanks in advance.
vData.equals("S") ? true : false
or in this particular case obviously one could just write
vData.equals("S")
Yeah, the ternary op ? :
vData.equals("S") ? true : false
The main difference between the Java ternary operator and IIf is that IIf evaluates both the returned value and the unreturned value, while the ternary operator short-circuits and evaluates only the value returned. If there are side-effects to the evaluation, the two are not equivalent.
You can, of course, reimplement IIf as a static Java method. In that case, both parameters will be evaluated at call time, just as with IIf. But there is no builtin Java language feature that equates exactly to IIf.
public static <T> T iif(boolean test, T ifTrue, T ifFalse) {
return test ? ifTrue : ifFalse;
}
(Note that the ifTrue and ifFalse arguments must be of the same type in Java, either using the ternary operator or using this generic alternative.)
if is the same as the logical iff.
boolean result;
if (vData.equals("S"))
result = true;
else
result = false;
or
boolean result = vData.equals("S") ? true : false;
or
boolean result = vData.equals("S");
EDIT: However its quite likely you don't need a variable instead you can act on the result. e.g.
if (vData.equals("S")) {
// do something
} else {
// do something else
}
BTW it may be considered good practice to use
if ("S".equals(vData)) {
The difference being that is vData is null the first example will throw an exception whereas the second will be false. You should ask yourself which would you prefer to happen.

Categories