Does Java optimize function calls for unnecessary boolean comparisons at runtime? - java

Will java actually call all three functions at runtime if one of them does not return true?
Often for debugging purposes, I like to see the result of these conditional checks in the debugger and putting them in one line makes that much more difficult. If there are half a dozen checks, then the code gets to be more unreadable.
boolean result1 = CheckSomething();
boolean result2 = CheckSomethingElse();
boolean result3 = CheckSomeOtherThing();
boolean finalResult = result1 && result2 && result3;
If Java doesn't optimize this conditional at runtime, then better performance should be achieved by writing the code like this at a cost of not being able to easily see the intermediary values in the debugger.
boolean finalResult = CheckSomething() && CheckSomethingElse() && CheckSomeOtherThing();

In general your code snippets are not equivalent. The first version must behave as-if all functions are called since you call them unconditionally in your code.
The second version of your code:
boolean finalResult = CheckSomething() && CheckSomethingElse() && CheckSomeOtherThing();
is not equivalent because the && operation is shortcut, so the remaining functions will not be called if any returns false.
When running in the interpreter, you can expect that the first version of your code will actually call all the methods.
Now, the interesting part: after the code is compiled, the compiler is now able to "look into" the various functions determine that they are pure functions, without side effects, and it may compile the two versions identically. In fact, if the functions are very simple, it may be better to compile both versions to always call all three functions, since combining three boolean results and checking it once may be much faster if any of the results are unpredictable.
The compiler may not always be able to determine whether a function has side effects, or there may actually be side effects that only you know don't matter (e.g., an ArrayOutOfBoundsException that you know won't occur but the compiler can't prove). So it's generally better to write the second form, which allows to compiler to use short-circuit evaluation regardless of what it is able to prove about the functions.

You can write this:
boolean result1 = condition1();
boolean result2 = result1 && condition2();
boolean result3 = result2 && condition3();
This allows you to step through each condition, and to see the intermediate results without executing unnecessary code.
You can also set a single breakpoint after the result3 line, which shows you the first result that returned false.

Agreed, that the second example will keep evaluating until it reaches a false condition, then it will return "false". The short circuit operator && is being used, therefore once a false condition is encountered, evaluation stops.

Related

Setting boolean variable to condition?

Is there any noticeable difference between
boolean foo= bar>1;
and
boolean foo = bar>1? true:false;
I have noticed that in the first example, the condition is evaluated immediately, looking something like this.
int bar=3;
boolean foo= bar>1;
bar =0;
if(foo){
System.out.println("Foobar");
}
Would print Foobar, whereas if the condition were to be inside the if statement, it would not print at all. This so far is identical to giving the boolean variable a true/false value from the start with the ternary operator or if/else
The ternary is highly redundant. Given that the inequality will return a boolean result, you do not need to perform any kind of ternary operation on it whatsoever.
One thing I like to add along with, both of the code will generate the same bytecode. For the proof you can use the Java Class File Disassembler (javap)
use the command to disassemble the class files javap -c com.package.MyClass and you will find for the both of the code JVM will generate the same bytecode. Hence there is No benefit or harm for either of the two statement. But definitely ternary here is redaundant

About Recursion for Newbies in Java

So, I have this code, which is just the way I solved an exercise that was given to me, which consisted of creating a recursive function that received a number, and then gave you the sum of 1, all the numbers in between, and your number. I know I made it sound confusing, but here's an example:
If I inserted the number 5, then the returned value would have to be 15, because: 1+2+3+4+5 = 15.
public class Exercise {
public static void main(String[] args) {
int returnedValue = addNumbers(6);
System.out.print(returnedValue);
}
public static int addNumbers(int value) {
if (value == 1) return value;
return value = value + addNumbers(value-1);
}
}
Technically speaking, my code works just fine, but I still don't get why Eclipse made me write two returns, that's all I would like to know.
Is there a way I could only write "return" once?
Sure, you can write it with just one return:
public static int addNumbers(int value) {
if (value > 1) {
value += addNumbers(value - 1);
}
return value;
}
As you can see, it's done by having some variable retain the running result until you get to the end. In this case I was able to do it in-place in value, in other cases you may need to create a local variable, but the idea of storing your intermediate result somewhere until you get to the return point is a general one.
There should be two returns. Your first return says
if at 1: stop recurstion
and the second one says
continue recursion by returning my value plus computing the value less than me
You could combine them by using a ternary:
return value == 1 ? value : value + addNumbers(value - 1)
But it is not as readable.
Recursive funtions like
Fibbonacci's sequence
Fractals
Etc.
Use themselves multiple times because they contain themselves.
Feel free to correct me if I'm wrong, but I don't think there is a way to eliminate one of those returns unless you decide to put a variable outside of the method or change the method from being recursive.
In java, a method that returns a value, MUST return a value at some point, no matter what code inside of it does. The reason eclipse requires you to add the second return, is because the first return is only run if your if statement evaluates to true. If you didn't have the second return, and that if statement did not end up being true, java would not be able to leave that method, and would have no idea what to do, thus, eclipse will require you to add a return statement after that if statement.
These types of errors are called checked errors or compile time errors. This means that eclipse literally can not convert your code into a runnable file, because it does not know how; there is a syntax error, or you are missing a return, etc.
Recursive functions always have at least 2 paths, the normal ones that will recurse and the "end" paths that just return (Usually a constant).
You could, however, do something like this:
public static int addNumbers(int value) {
if (value != 1)
value = value + addNumbers(value-1);
return value;
}
But I can't say I think it's much better (Some people get as annoyed at modifying parameters as they do at multiple returns). You could, of course, create a new variable and set it to one value or the other, but then someone would get upset because you used too many lines of code and an unnecessary variable. Welcome to programming :) Your original code is probably as good as you're likely to get.
As for why "Eclipse" did that to you, it's actually Java--Java is better than most languages at making sure you didn't do something clearly wrong as soon as possible (In this case while you are typing instead of waiting for you to compile). It detected that one branch of your if returned a value and the other did not--which is clearly wrong.
Java is also very explicit forcing you to use a "return" statement where another language might let you get away with less. In Groovy You'd be tempted to eliminate the return and write something like:
def addNumbers(value){value + (value-1?0:addNumbers(value-1))}
just for fun but I certainly wouldn't call THAT more readable! Java just figures it's better to force you to be explicit in most cases.
From the wikipedia on recursion:
In mathematics and computer science, a class of objects or methods
exhibit recursive behavior when they can be defined by two properties:
A simple base case (or cases)—a terminating scenario that does not use recursion to produce an answer
A set of rules that reduce all other cases toward the base case
There are two returns because you have to handle the two cases above. In your example:
The base case is value == 1.
The case to reduce all other cases toward the base case is value + addNumbers(value-1);.
Source: https://en.wikipedia.org/wiki/Recursion#Formal_definitions
Of course there are other ways to write this, including some that do not require multiple returns, but in general multiple returns are a clear and normal way to express recursion because of the way recursion naturally falls into multiple cases.
Like the robots of Asimov, all recursive algorithms must obey three important laws:
A recursive algorithm must have a base case.
A recursive algorithm must change its state and move toward the base case.
A recursive algorithm must call itself, recursively.
Your if (value == 1) return value; return statement is the base case. That's when the recursion(calling itself) stops. When a function call happen, the compiler pushes the current state to stack then make the call. So, when that call has returned some value, it pulls the value from stack, makes calculation and return the result to upper level. That's why the other return statement is for.
Think of this like breaking up your problem:
addNumbers(3) = 3 + addNumbers(2) (this is returned by second one)
-> 2 + addNumbers(1) (this is returned by second one)
-> 1 (this is returned by base case)

Checking a variable on null value styles

I have 2 java statements:
if(myvar!=null)
if(null!=myvar)
Some people says that second form is better because it helps to avoid NPEs, is it true? What is generally beter to use in java?
if(myvar!=null)
if(null!=myvar)
Some people says that second form is better because it helps to avoid
NPEs, is it true?
No. These are exactly the same, and there is no risk of NPE here to avoid.
Maybe you confused the example with this situation:
if (myvar.equals("something"))
if ("something".equals(myvar))
Here, if myvar is null, the first form would throw an NPE, since .equals would be dereferencing a null value, but the second one works just fine, as the .equals implementation of String handles a null parameter gracefully, returning false in this example. For this reason, in this example, the 2nd form is generally recommended.
A related argument, which one of these is preferred?
if (myvar == null)
if (null == myvar)
Consider the possibility of a typo, writing a single = instead of ==:
if (myvar = null)
if (null = myvar)
If myvar is a Boolean, then the first form will compile, the second form will not. So it may seem that the second form is safer. However, for any other variable type, neither form will compile. And even in the case of a Boolean, the damage is very limited, because regardless of the value of myvar, the program will always crash with an NPE when the if statement is reached, due to unboxing a null value.
Since no test will ever get past this statement, and since you should not release untested code, making such mistake is unrealistic.
In short, the safety benefit is so marginally small that it's practically non-existent, so I don't see a reason to prefer this unusual writing style.
Update
As #Nitek pointed out in a comment, an advantage of adopting the second form could be if you make it a habit, so that when you program in other languages where myvar = null might compile, you'd be slightly safer, out of your "good habits".
I'd still point out that in many languages comparisons with null are special, with no possibility of such typo errors. For example in Python, myvar == None is incorrect, and should be written as myvar is None, so there's no more == to mistype.
Strictly speaking, although the null = myvar writing style will not protect you in all languages, it might protect you in some, so I'd have to admit it seems to be a good habit.
This is not true, they are the same.
I prefer the first one because i think it reads better.
if(myvar!=null)
if myvar is not equal to null
and
if(null!=myvar)
if null is not equal to myvar
There is no certain difference in both of them both refer to the same check
if(myvar!=null)
if(null!=myvar)
both are the exact same things.
But in depper context it is the Yoda Condition.
It is generally criticized because of its readability issues, so try to make every thing simple for yourself and for other people who might read your code as this is not a standard notation.
This is primary opinion based, but I always go with
if (variable == null)
if (variable != null)
because imo it´s a better programming style.
And a short answer to your post, no difference between them.
There is no practical difference in your case.
15.21. Equality Operators
The equality operators are commutative if the operand expressions have no side effects.
That is, you can have a situation where the LHS and RHS matter because evaluating them can cause a change in the other, but not if one of them is the keyword null.
Consider the following example:
public class Example {
static int x = 0;
public static void main(String[] args) {
System.out.println(doit() == x); // false
System.out.println(x == doit()); // true
}
static int doit() {
x++;
return 0;
}
}
Furthermore,
15.21.3. Reference Equality Operators == and !=
The result of != is false if the operand values are both null or both refer to the same object or array; otherwise, the result is true.
shows that there is no difference in the evaluation.
As Nitek wrote in the comment to my initial question:
The second one prevents typos like "myvar=null" because "null=myvar" won't compile. Might save you some trouble.
So, we have a BIG advantage of the second form - it helps to prevent serious logic error. Example:
Boolean i=false;
....
if(null=i){
}
won't compile
but
Boolean i=false;
....
if(i=null){
}
will
But the second form has a big disadvantage - it's reading difficulties.
So I would say that in 99% cases the first form is ok, but I prefer to use the second form. If you are sure you won't mix == and = up, use the first form. If not, use the second. I'm sure there are a couple of other cases when the second form is preferred, but can't remind it at the moment.

Conditional ternary with method call to db

So i've been lurking around here for the past few years and have finally come to the situation where I did NOT find an existing answer here. The question itself is pretty simple though.
Assume the following statement (no language specific syntax):
var result = fetchFromDb() == null ? defaultValue : fetchFromDb().property;
What I want to know is: does the compiler in Java or C# have a way to optimise this statement or will there really be two calls to the fetchFromDb() method meaning two DB access calls, two execution plans and so on?
I already have tested this in Java and found out that the method is called twice, but I have no idea about eventual caching in the background or anything alike.
So: is using the ternary conditional with methods a bad practice? Is there a way to cache the value compared against inline in order to preserve the beauty of this style?
Yes, it will always be two calls. The fact is between the first call and the second call, the result of fetchFromDb() can change. There is no way for the compiler to predict that change in value, unless it is a well known deterministic function. Deterministic being the key word here. Even then there may not be compiler optimization for such things.
Using a ternary condition with methods is not bad practice per se, but it is less readable than a simple if statement.
The only way to guarantee a single call is to code a single call.
var result;
var fetchResult = fetchFromDb();
if (fetchResult == null) {
result = defaultValue;
} else {
result = result.property;
}
Or if you insist on using a ternary
var fetchResult = fetchFromDb()
var result = (fetchResult == null) ? defaultValue : result.property;
I really think this is much clearer than a ternary. Having code on a single line does not infer beautiful code.
Actually
var result = fetchFromDb() == null ? defaultValue : fetchFromDb().property;
Will make two calls in the else case. To avoid the double call:
var fetch = fetchFromDb();
var result = fetch != null ? fetch.property : defaultValue;

Boolean expressions optimizations in Java

Consider the following method in Java:
public static boolean expensiveComputation() {
for (int i = 0; i < Integer.MAX_VALUE; ++i);
return false;
}
And the following main method:
public static void main(String[] args) {
boolean b = false;
if (expensiveComputation() && b) {
}
}
Logical conjunction (same as &&) is a commutative operation. So why the compiler doesn't optimize the if-statement code to the equivalent:
if (b && expensiveComputation()) {
}
which has the benefits of using short-circuit evaluation?
Moreover, does the compiler try to make other logic simplifications or permutation of booleans in order to generate faster code? If not, why? Surely some optimizations would be very difficult, but my example isn't simple? Calling a method should always be slower than reading a boolean, right?
Thank you in advance.
It doesn't do that because expensiveComputation() may have side effects which change the state of the program. This means that the order in which the expressions in the boolean statements are evaluated (expensiveComputation() and b) matters. You wouldn't want the compiler optimizing a bug into your compiled program, would you?
For example, what if the code was like this
public static boolean expensiveComputation() {
for (int i = 0; i < Integer.MAX_VALUE; ++i);
b = false;
return false;
}
public static boolean b = true;
public static void main(String[] args) {
if (expensiveComputation() || b) {
// do stuff
}
}
Here, if the compiler performed your optimization, then the //do stuff would run when you wouldn't expect it to by looking at the code (because the b, which is originally true, is evaluated first).
Because expensiveComputation() may have side-effects.
Since Java doesn't aim to be a functionally pure language, it doesn't inhibit programmers from writing methods that have side-effects. Thus there probably isn't a lot of value in the compiler analyzing for functional purity. And then, optimizations like you posit are unlikely to be very valuable in practice, as expensiveComputation() would usually be required to executed anyway, to get the side effects.
Of course, for a programmer, it's easy to put the b first if they expect it to be false and explicitly want to avoid the expensive computation.
Actually, some compilers can optimise programs like the one you suggested, it just has to make sure that the function has no side-effects. GCC has a compiler directive you can annotate a function with to show that it has no side-effects, which the compiler may then use when optimizing. Java may have something similar.
A classic example is
for(ii = 0; strlen(s) > ii; ii++) < do something >
which gets optimized to
n = strlen(s); for(ii = 0; n > ii; ii++) < do something >
by GCC with optimization level 2, at least on my machine.
The compiler will optimize this if you run the code often enough, probably by inlining the method and simplifying the resulting boolean expression (but most likely not by reordering the arguments of &&).
You can benchmark this by timing a loop of say a million iterations of this code repeatedly. The first iteration or two are much slower than the following.
The version of java I am using optimises a in an expression a && b but not with b.
i.e. If a is false, b does not get evaluated but if b was false it did not do this.
I found this out when I was implementing validation in a website form: I created messages to display on the web-page in a series of boolean methods.
I expected of the fields in the page which were incorrectly entered to become highlighted but, because of Java's speed-hack, the code was only executed until the first incorrect field was discovered. After that, Java must have thought something like "false && anything is always false" and skipped the remaining validation methods.
I suppose, as a direct answer to your question, if you make optimisations like this, your program may run slower than it could. However, someone else's program will completely break because they have assumed the non-optimised behaviour like the side effect thing mentioned in other answers.
Unfortunately, it's difficult to automate intelligent decisions, especially with imperative languages (C, C++, Java, Python,... i.e the normal languages).

Categories