Do if statements that call methods on an object modify the object? - java

I'm trying to perform actions on my object, but only do so if certain things are true. I have several methods which is consider "action" methods, they do some action that attempts to modify the object and returns true/false if that action can be done.
Example 1
Thing thing = new Thing();
if (thing.changeSomething()){
if (thing.shouldDoSomething()){
//do more things
}
}
I know about compound boolean expressions like to check if a number in a valid range of values
if(number>0 && number<=10)
//number is valid
But haven't really done much when the sub-expressions are method calls
Example 2
if ( thing.changeSomething() && (thing.shouldDoSomething() ){
//do more things
}
Is Example 2 the same as Example 1?
Will Example 2 call the shouldDoSomething() method? Because I don't want this to happen because sometimes shouldDoSomething() actually has other implications & changes other aspects of the object.

Calling
if (thing.changeSomething()){
if (thing.shouldDoSomething()){
is esentially equivalent to
if (thing.changeSomething() && thing.shouldDoSomething()){
I guess they are translated to the exact same IL.
However as mentioned in the comments the second method is only executed if the first one evaluates to true. If the first operand of an &&-operator is already false there´s no need to execute the second also, so your shouldDoSomething-method isn´t executed if changeSomething allready returned false.
Btw. this applies to both Java and C#.

In Java, the logical AND operator && is a short circuit operator, meaning the right side is not evaluated if the result of the expression can be determined solely from the left operand. Specifically, if the left side evaluates to false, the whole expression is false and the right side does not need to be evaluated to determine that.
In the case of your function calls:
if ( thing.changeSomething() && (thing.shouldDoSomething() ){
//do more things
}
If thing.changeSomething() returns false then thing.shouldDoSomething() will not be called since the expression evaluates to false regardless of what this function may return. So yes, the above is equivalent to:
if ( thing.changeSomething() ) {
if (thing.shouldDoSomething() ){
//do more things
}
}

The simple answer and what it comes down to is, it depends on if the thing.changeSomething() method returns a boolean. It is going to create problems if it does not. It is very possible to define this method to do something and return true after it does what it was supposed to do. In which case the second example would work.
If it does not return boolean you should see an error or it might not work to your liking.
It should call the method when to do it that way in example 2. What I would recommend because you don't want that is to create getter() and checker() methods that you use to get info on the object without having to change it. This can also be done with data fields, depends on class structure.
Hope this is more digestible and helps!

Related

Are the || ('or') symbol and Stream.of(..).anyMatch(e-> e==true) functionally equivalent? [duplicate]

This question already has answers here:
Why is Streams.allMatch(in Java8) trying to evaluate all the expressions even if the value can be determined midway?
(2 answers)
Closed 2 years ago.
Are || and Stream.of(..).anyMatch(e-> e==true) functionally equivalent when applied to the same series of conditions in the same order?
Task: Run a quick test on a series of conditions to determine whether any are true.
Possible solutions:
- Separate each condition with an ‘or’ symbol (||)
- Include each condition in a Stream.of(..) statement that is appended with .anyMatch(e-> e==true)
The documentation for anyMatch(..) states, “Returns whether any elements of this stream match the provided predicate. May not evaluate the predicate on all elements if not necessary for determining the result [emphasis added].”
Based on this statement, my understanding is that the two solutions indicated above are functionally the same, so that if the second element in a serious of four is the first element that is true, then elements three and four won’t be evaluated.
In practice, however, this seems not to be true. Consider the following where item is null, empty is true and UtilMethods.isEmpty(..) is a custom library method that tests if a given parameter is null or an empty String (""):
#Override
protected void updateItem(Pair<K, V> item, boolean empty) {
super.updateItem(item, empty);
boolean test1 = empty
|| Objects.isNull(item)
|| UtilMethods.isEmpty(item.toString())
|| Objects.isNull(item.getValue());
boolean test2 = Stream.of(
empty,
isNull(item),
UtilMethods.isEmpty(item.toString()),
isNull(item.getValue()))
.anyMatch(e -> e == true);
}
The || code runs as expected. However, the Stream.of(..).anyMatch(..) throws a NullPointerException when the third element is reached because item is null.
This doesn’t make sense in view of the documentation for anyMatch(..) that is referenced above, which suggests that the third element shouldn’t even be reached. Or am I missing something here?
Thanks
UtilMethods.isEmpty(item.toString()) is evaluated before Stream.of() is executed, so it will throw a NullPointerException regardless of whether or not you call anyMatch afterwards.
Stream.of(), just as any method call, evaluates all of its arguments before being executed, so it must evaluate UtilMethods.isEmpty(item.toString()).
You can see the same behavior in a much simpler snippet:
String s = null;
Stream<Integer> stream = Stream.of (5,s.length());
Hence, the documentation of anyMatch is irrelevant to the behavior you observed.
Your observation is correct. The two code snippets are indeed not the same. The important behaviour that || does, that Stream does not, is that || is short circuiting. When the first operand is true, || stops evaluating immediately. This is not true for the stream operation you have written. All 4 expressions:
empty,
isNull(item),
UtilMethods.isEmpty(item.toString()),
isNull(item.getValue())
Are evaluated before the stream even runs. Yes, anyMatch is lazy, but of is not. See what I mean? anyMatch will not evaluate e == true for every element if a previous element evaluated to true already. This does not apply to of.
To replicate the || behaviour, you'd have to wrap those 4 expressions into Supplier<Boolean>s, and evaluate them in anyMatch:
boolean test2 = Stream.<Supplier<Boolean>>of(
() -> empty,
() -> isNull(item),
() -> UtilMethods.isEmpty(item.toString()),
() -> isNull(item.getValue()))
.anyMatch(Supplier::get);
As you may long know, || uses shortcut evaluation, that is, if the first item it true, the second is never evaluated. This fact saves you from a NullPointerException in hte first case.
A stream pipeline has a similar behaviour: the final anyMatch only pulls enough elements from the stream to determine whether there is a match. So it may surprise that you get the exception. The explanation of Eran is correct, though: All the arguments of Stream.of() are evaluated before of is called to create the stream. This causes the exception. In other words, the stream never gets created. So the evaluation order in the stream never gets relevant in this case.
That this must be so is probably clearer to see if for a moment we forget that this is a stream operation and just look at it as Java method calls. The structure of the calls in your stream code is similar to the following, only I have simplified it a bit:
SomeClass.foo(ref.bar()).baz();
The sunshine order of evaluation of this expression is dictated by Java:
ref.bar() is evaluated to get the argument to pass to foo();
foo() is called;
baz() is called on the object returned from foo().
However if ref is null, the first step throws a NullPointerException and steps 2 and 3 are never performed. So there is nothing foo() nor baz() can do to change the order of evaluation nor to prevent the exception from happening. Similarly in your code there is nothing the stream pipeline can do to prevent all arguments to Stream.of() to be evaluated before of() is called to create the stream.
The rules about the order of evaluation were laid down in Java long before streams were introduced in the library and are similar to other programming languages. They wisely did not change them radically when introducing streams in Java 8. Sweeper in his answer shows a nice way to obtain the evaluation order you had expected.
Shortcut evaluation is explained in many places. One is here: What is the difference between the | and || or operators?

if i inside an if statement checks if a method returns true, will the actual code in the method be executed?

Okay so.. i have a method that basically checks if the player can buy the field and if he can then sets him as the owner and return true. the method i am referring to is buyFieldFromBank in the if statement.
But i want to check if my method returns true, and if it do, ask the user if he wants to buy it. can i actually do it like this? or will the code allready have set him as owner in the if statement? Or does it only "check" if it turns true, without actually executing the code?
if(landRegistry.buyFieldFromBank(currentPlayer, newPosID)==true){
if(GUI.getUserButtonPressed(currentPlayer.getName() + ", vil du købe " + newPosition.getFieldName() + "Ja", "Nej")=="Ja"){
landRegistry.buyFieldFromBank(currentPlayer, newPosID);
Couple of obvious issues:
1) You're using == instead .equals to compare Strings in the 2nd if, well tread debate covering that issue here: Link
2) By calling landRegistry.buyFieldFromBank you are executing that method, so it will already be done. You need a method like landRegistry.isUserEligible(currentPlayer,newPosId) to check in that first if statement. Then if it passes both the first & secondary conditions it should call the buyFieldFromBank method. Also it may be worth considering if that 2nd if should belong in the isUserEligible method call; if it's part of the logic of determining eligibility it might fit best there.
3) The == true part of the first if is redundant if the method you're calling returns a boolean. So you can drop that part and just have the method call itself.
If you call a method with . you're executing that method always. How else can it work? You should change your design.

Java Nested If condition

I suddenly got a strange doubt..
I want to know whether
if(a && b) {
}
is same as
if(a) {
if(b) {
}
}
or not..
Both the cases giving me the same result. But, I'm still not feeling comfort to use the first method in my project.
Any helps??
If using If-else statement then
if loop will execute only condition is true:---
if(condition){
//execute when it is true
}
In your case you are using Two variable a and b with AND OPERATOR.
The property of AND OPERATOR is If All giving value is true then it will return true otherwise false.
If you want to use your method then
/*
check for your in a and b
both are true
*/
then your method will be execdute
if(a && b) {
//if a and b both return true(a=true,b=true)
}
It is same. In the first case compiler guarantees that second condition will not be executed if first condition returns false.
Yes they are the same as far as functionality is concerned. && is a short-circuit operator. So, in a && b, b will be evaluated only if a is evaluated to true.
Same is the case with nested if. The inner if will be executed only when outer if is evaluated to true. But the 1st one shows your intents better if you want to execute the code only when both a and b are true.
But, one difference is that, you can implement the functionality of a = true, b = false, in 2nd case by adding that functionality before the nested if starts. But, you can't do that in 1st
a && b means if a is tue and so is b, so:
if(a && b) {
}
does not leave space for indecision, it's all or nothing, only if a && b the if body will be executed, while
if(a) {
if(b) {
}
}
leaves you space to act if a, without considering b for the moment. So if you want to do some actions before checking b you can.
If you do not have anything to do just when a then the two are equal and imho the first is to prefer because it is more readable.
Yes, it's the same thing. The && operator checks if both conditions are true. If you nest your if statements like that, it amounts to the same thing since the second one will only be checked if the first one is true. Only separate them if you need something done that involves a being true but not b.
In both cases It's just short-circuiting.
in which the second argument is only executed or evaluated if the first argument does not suffice to determine the value of the expression:
The short-circuit expression x Sand y (using Sand to denote the short-circuit variety) is equivalent to the conditional expression if x then y else false; the expression x Sor y is equivalent to if x then true else y.
Coming to the syntax,The first thing (if(a && b) )which beautifies your code and and more readable.
Both conditions are same as in first one: if(a && b){ }, you are checking with && operator So, in a && b, b will be evaluated only if a is evaluated to true.
while in second case, first of all it will check value of a in outer if condition and if it satisfies then it will check value of b in inner if condition.
But fist one is more preferable.
As many have stated before me: they are technically equivalent (right down to the short-circuit semantics).
But I dare say the && operator is preferred in any situation, and that it's not just a matter of taste. The nested if is harder to read in day-to-day code with more than just control statements, and leaves more room for error.
Mostly because if(b) communicates: "the following block is only executed if b is true".
But that's not what happens! The block is only executed if a and b are true (which is exactly what the first method communicates rather elegantly). It's very easy to unintentionally pull it out of the if(a) context (any IDE has plenty of ways to shuffle code around) and create a bug.
The nested if also leaves a lot of room for horrible code later on. Wedging code between the inner and outer can make it tricky to understand which code is executed when - especially if a and b are complex expressions. And things become really nasty when somebody decides to toss in a few else-statements.. :-) There's simply no way to get into that mess with a single && operator.
Some might argue this "flexibility" is a reason to use the second method, but I'd argue there is almost always a way to rewrite that cleanly using explicit conditions. Coding is hard enough without spending all your brain cycles on control logic.
Bottom line: every Java programmer understands the semantics of the conditional-AND operator. Relying on built-in language constructs instead of rolling your own equivalents goes a long way towards maintainability and correctness.
Hope this helps.

Lazy evaluation not working as it should

I had to evaluate a boolean expression frecuently, so I converted it in a private method in it's class. Here is the code it's causing me trouble:
//"x", "y" and "team" are already defined
return (map.isWalkable(x,y) &&
(!map.isOccupied(x,y) || map.getOccupant(x, y).getTeam() == team) );
Methods should be preety much self-explanatory as for the purpose of this question. Now, isWalkable and isOccupied both return a boolean, and getOccupant is the only method returning an object reference. The problem is that I'm getting a NullPointerException when executing this piece of code, and that shouldn't be happening because isOccupied returns true if and only if map.getOccupant != null (that's actually what that method returns). So with a language supporting lazy boolean evaluation from left to right (as I assume java is, or at least that's what I was able to read) the getOccupant method should never be executed whenever it would return null am I right?
Is this more compiler-dependent than I thought it was? Should it be safer if I used if statements, or is there simply something obvious I'm missing here, maybe operations get resolved the other way round.
The issue is your parenthesis. Try
return (map.isWalkable(x,y) && (!map.isOccupied(x,y) || map.getOccupant(x, y).getTeam() == team));
Simply put, no, lazy evaluation is not broken. Your code is.
Either map is null, or map.getOccupant(x,y) returns null.
If you put them on their own lines and go through them with a debugger, you'll notice that "oh no, I was so stupid and didn't notice that".
The compiler, JVM or anything else has nothing to do with this.

Reason for the existence of non-short-circuit logical operators

When used with boolean operands, & and | become logical operators per Section 15.22.2 of the JLS. Unlike && and ||, however, these don't short-circuit; they always evaluate both sides. I have a silly question: Why are the less-efficient non-short-circuit logical operators (&, |) still there, when we have the more-efficient short-circuit logical operators (&&, ||)? I mean, what is the real usage of the non-short-circuit logical operators, as opposed to with the short-circuit logical operators? In other words, what is the usage of always evaluating both sides by using the non-short-circuit logical operators?
Updated answer:
Apologies, I missed the word "logical" in your question even though it is there. (I've taken the liberty of emphasizing it a bit with an edit.)
Consider the case where you want any side-effects to always occur, regardless of whether the left-hand expression evaluates true or false. E.g., contrast:
if (foo() & bar()) {
// Only call this if both operations returned true
}
with
if (foo() && bar()) {
// Only call this if both operations returned true
}
Let's assume both foo and bar have effects that we want to have happen regardless of whether foo returns true or false. In the first one above, I know that bar will always get called and have its effect. In the latter, of course, bar may or may not get called. If we didn't have the non-short-circuit version, we'd have to use temporary variables:
boolean fooResult, barResult;
fooResult = foo();
barResult = bar();
if (fooResult && barResult) {
// ...
}
You might argue (I probably would) that you should do that anyway, because it's way too easy to misread if (foo() & bar()), but there we go, a pragmatic reason for having non-short-circuit versions.
Original answer:
How would you propose & (or |) be a short-circuited operator? With && and ||, it makes sense because you're dealing with boolean conditions: They can be true or false, there are no shades of grey. But & and | deal with bits, not booleans. The result is a number. I mean, I guess & could not evaluate the right-hand side if the left-hand side were 0, and similarly | could not evaluate it if the left-hand side were all-bits-on for whatever the type was, but I don't see much point to making the one edge case of each operator significant (as compared to the 254 or more other cases).
There are instances where the components of a boolean expression involve operations that you'd want to have executed in all cases. Consider the following example of checking a password for validity:
while ( !password.isValid() & (attempts++ < MAX_ATTEMPTS) ) {
// re-prompt
}
If the second condition was not evaluated due to short-circuiting, attempts would never be incremented. Thus greater programmer flexibility is enabled.
My case (C++):
void setFields(Parameters bundle)
{
if (setIfDifferent(&field1, bundle.value1) |
setIfDifferent(&field2, bundle.value2) |
setIfDifferent(&field3, bundle.value3)) {
storeState();
}
}
setIfDifferent() sets the object's field with new value if they differ, in which case it returns true; or it returns false in case the field's and the new value are the same. So, we want to try to set all fields, and if any of them changed, then we want to store new object's state.
You can have some side-effects in logical expression, for example you can assign simultaneously with checking. This may work wrongly if only one part evaluated.
Can't remember good example now, but remember that I was in need of "non-short-circuit" operators sometimes.
Hmmm.... Below is WRONG example, which won't work without "non-short-circuit" OR:
if( (object1=getInstance1()).getNumber() == 1 || (object2=getInstance2()).getNumber() == 2 ) {
// do something which requires bot object1 and object2 assigned
}
In my case, I have two methods that compare two different but related objects (Object2 is an attribute of Object1) to see if there were any changes. An update needs to happen if either are updated, but both need to be evaluated so that the objects will be modified if both have been changed. Therefore, a single pipe "OR" comparison is required.
EX:
if (compare(object1, currentObject1) | comparison(object2, currentObject2)) {
updateObject1(object1);
}
Technically, & and | are not logical, they're bitwise operators that become logical operators when associated with booleans.
There are times when you'd want to include assignment expressions inside your logical expressions.
Say:
if(a = (checkForSomeCondition()) | b = checkForAnotherCondition())
{
//now do something here with a and b that has been cached
}
If I had used ||, I'd not be able to perform the above check and would have had to split the assignments into separate statements. I've never come across scenarios like this during application development, but come across it a few times while writing algorithms.
Of course, you could use unary operators on the logical expressions or pass variables by reference into a predicate, but those seem like less common cases than the above.

Categories

Resources