Setting boolean variable to condition? - java

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

Related

can we use ternary operator just like an if-else statement in every case, where no nesting is required? [duplicate]

This question already has answers here:
Ternary Operator
(4 answers)
Closed 5 months ago.
Is there a way to implement this in a ternary operation. I'm very new to that ternary stuff, maybe you could guide me.
if(selection.toLowerCase().equals("produkt"))
cmdCse.setVisible(true);
else
cmdCse.setVisible(false);
This one doesn't seem to work.
selection.toLowerCase().equals("produkt")?cmdCse.setVisible(true):cmdCse.setVisible(false);
In this case, you don't even need a ternary operator:
cmdCse.setVisible(selection.toLowerCase().equals("produkt"));
Or, cleaner:
cmdCse.setVisible(selection.equalsIgnoreCase("produkt"));
Your version:
selection.toLowerCase().equals("produkt")? cmdCse.setVisible(true): cmdCse.setVisible(false);
is semantically incorrect: ternary operator should represent alternative assignments, it's not a full replacement for if statements. This is ok:
double wow = x > y? Math.sqrt(y): x;
because you are assigning either x or Math.sqrt(y) to wow, depending on a condition.
My 2cents: use ternary operator only when it makes your program clearer, otherwise you will end up having some undecipherable one-liners.
Perhaps
cmdCse.setVisible(selection.toLowerCase().equals("produkt"));
The ternary operator isn't exactly like an if statement. A ternary operator has to "return" something from both sides, so putting void method calls like setVisible() there won't work.
Instead, you could do something like this without ternary operators at all:
cmdCse.setVisible(selection.toLowerCase().equals("product"));
But just to demonstrate the point, the ternary equivalent would look something like this:
cmdCse.setVisible(selection.toLowerCase().equals("product") ? true : false);
Notice how now the ternary operator "returns" true or false on both sides instead of simply calling a void method.
I think this will work for you
cmdCse.setVisible(selection.toLowerCase().equals("produkt"));
Directly from the docs
Use the ?: operator instead of an if-then-else statement if it makes your code more readable; for example, when the expressions are compact and without side-effects (such as assignments).
In your case cmdCse.setVisible(true / false); doesn't return anything, and the operation also has side effects (it changes state of cmdCse), so the conditional operator cannot be used here (when you do use the operator, both of the ? and : branches must have the same return type).
As an aside, please note that .. ? .. : .. should be referred to as the conditional operator
On the issue of using exceptions
I want to answer the issue of the exceptions here as this question is a duplicate for another question concerning throwing exceptions from a ternary expression, but this is not addressed in the above answers.
The general consensus is that it cannot be done directly as in:
public Character next() {
return hasNext() ? s.charAt(cur++) : throw new NoSuchElementException(); // compilation error
}
will give you a compilation error, but as Clement pointed out it can be done via a declared extra function. It can also be done via (ab-)using lambda expressions.
public Character next() {
return hasNext() ? s.charAt(cur++) : ((Function<Integer, Character>) x -> {throw new NoSuchElementException();}).apply(1);
}
for sure this is not that pretty (it is pretty ugly) and I would not recommend to do that for readability purposes, but sometimes there are circumstances which might warrant exceptionally doing that. If someones figures out a way to do it without the cast it would be a bit more readable.
If you had a function throwNoSuchElementException() defined somewhere that you use more than once, it would look a bit more readable:
public Character next() {
return hasNext() ? s.charAt(cur++) : throwNoSuchElementException();
}
(P.S.: I included this answer for completeness sake, as I asked myself can it really be not done?)
(P.S.S.: If the exception to be thrown is not a runtime exception this will not work so easily and would require even more handstands - not really worth it)
Here are my tips, if you need to set things to booleans, then simple use setBoolean(condition), else, if you need to set a variable to a non boolean value, then use var=condition?result1:result2(or the variable itself if you don't want to change if condition is false), otherwise, use if else.

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

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.

Missing return statement in a non-void method compiles

I encountered a situation where a non-void method is missing a return statement and the code still compiles.
I know that the statements after the while loop are unreachable (dead code) and would never be executed. But why doesn't the compiler even warn about returning something? Or why would a language allow us to have a non-void method having an infinite loop and not returning anything?
public int doNotReturnAnything() {
while(true) {
//do something
}
//no return statement
}
If I add a break statement (even a conditional one) in the while loop, the compiler complains of the infamous errors: Method does not return a value in Eclipse and Not all code paths return a value in Visual Studio.
public int doNotReturnAnything() {
while(true) {
if(mustReturn) break;
//do something
}
//no return statement
}
This is true of both Java and C#.
Why would a language allow us to have a non-void method having an infinite loop and not returning anything?
The rule for non-void methods is every code path that returns must return a value, and that rule is satisfied in your program: zero out of zero code paths that return do return a value. The rule is not "every non-void method must have a code path that returns".
This enables you to write stub-methods like:
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
That's a non-void method. It has to be a non-void method in order to satisfy the interface. But it seems silly to make this implementation illegal because it does not return anything.
That your method has an unreachable end point because of a goto (remember, a while(true) is just a more pleasant way to write goto) instead of a throw (which is another form of goto) is not relevant.
Why doesn't the compiler even warn about returning something?
Because the compiler has no good evidence that the code is wrong. Someone wrote while(true) and it seems likely that the person who did that knew what they were doing.
Where can I read more about reachability analysis in C#?
See my articles on the subject, here:
ATBG: de facto and de jure reachability
And you might also consider reading the C# specification.
The Java compiler is smart enough to find the unreachable code ( the code after while loop)
and since its unreachable, there is no point in adding a return statement there (after while ends)
same goes with conditional if
public int get() {
if(someBoolean) {
return 10;
}
else {
return 5;
}
// there is no need of say, return 11 here;
}
since the boolean condition someBoolean can only evaluate to either true or false, there is no need to provide a return explicitly after if-else, because that code is unreachable, and Java does not complain about it.
The compiler knows that the while loop will never stop executing, hence the method will never finish, hence a return statement is not necessary.
Given your loop is executing on a constant - the compiler knows that it's an infinite loop - meaning the method could never return, anyway.
If you use a variable - the compiler will enforce the rule:
This won't compile:
// Define other methods and classes here
public int doNotReturnAnything() {
var x = true;
while(x == true) {
//do something
}
//no return statement - won't compile
}
The Java specification defines a concept called Unreachable statements. You are not allowed to have an unreachable statement in your code (it's a compile time error). You are not even allowed to have a return statement after the while(true); statement in Java. A while(true); statement makes the following statements unreachable by definition, therefore you don't need a return statement.
Note that while Halting problem is undecidable in generic case, the definition of Unreachable Statement is more strict than just halting. It's deciding very specific cases where a program definitely does not halt. The compiler is theoretically not able to detect all infinite loops and unreachable statements but it has to detect specific cases defined in the specification (for example, the while(true) case)
The compiler is smart enough to find out that your while loop is infinite.
So the compiler cannot think for you. It cannot guess why you wrote that code. Same stands for the return values of methods. Java won't complain if you don't do anything with method's return values.
So, to answer your question:
The compiler analyzes your code and after finding out that no execution path leads to falling off the end of the function it finishes with OK.
There may be legitimate reasons for an infinite loop. For example a lot of apps use an infinite main loop. Another example is a web server which may indefinitely wait for requests.
In type theory, there is something called the bottom type which is a subclass of every other type (!) and is used to indicate non-termination among other things. (Exceptions can count as a type of non-termination--you don't terminate via the normal path.)
So from a theoretical perspective, these statements that are non-terminating can be considered to return something of Bottom type, which is a subtype of int, so you do (kind of) get your return value after all from a type perspective. And it's perfectly okay that it doesn't make any sense that one type can be a subclass of everything else including int because you never actually return one.
In any case, via explicit type theory or not, compilers (compiler writers) recognize that asking for a return value after a non-terminating statement is silly: there is no possible case in which you could need that value. (It can be nice to have your compiler warn you when it knows something won't terminate but it looks like you want it to return something. But that's better left for style-checkers a la lint, since maybe you need the type signature that way for some other reason (e.g. subclassing) but you really want non-termination.)
There is no situation in which the function can reach its end without returning an appropriate value. Therefore, there is nothing for the compiler to complain about.
Visual studio has the smart engine to detect if you have typed a return type then it should have a return statement with in the function/method.
As in PHP Your return type is true if you have not returned anything. compiler get 1 if nothing has returned.
As of this
public int doNotReturnAnything() {
while(true) {
//do something
}
//no return statement
}
Compiler know that while statement itself has a infinte nature so not to consider it. and php compiler will automatically get true if you write a condition in expression of while.
But not in the case of VS it will return you a error in the stack .
Your while loop will run forever and hence won't come outside while; it will continue to execute. Hence, the outside part of while{} is unreachable and there is not point in writing return or not. The compiler is intelligent enough to figure out what part is reachable and what part isn't.
Example:
public int xyz(){
boolean x=true;
while(x==true){
// do something
}
// no return statement
}
The above code won't compile, because there can be a case that the value of variable x is modified inside the body of while loop. So this makes the outside part of while loop reachable! And hence compiler will throw an error 'no return statement found'.
The compiler is not intelligent enough (or rather lazy ;) ) to figure out that whether the value of x will be modified or not. Hope this clears everything.
"Why doesn't the compiler even warn about returning something? Or why would a language allow us to have a non-void method having an infinite loop and not returning anything?".
This code is valid in all other languages too (probably except Haskell!). Because the first assumption is we are "intentionally" writing some code.
And there are situations that this code can be totally valid like if you are going to use it as a thread; or if it was returning a Task<int>, you could do some error checking based on the returned int value - which should not be returned.
I may be wrong but some debuggers allow modification of variables. Here while x is not modified by code and it will be optimized out by JIT one might modify x to false and method should return something (if such thing is allowed by C# debugger).
The specifics of the Java case for this (which are probably very similar to the C# case) are to do with how the Java compiler determines if a method is able to return.
Specifically, the rules are that a method with a return type must not be able to complete normally and must instead always complete abruptly (abruptly here indicating via a return statement or an exception) per JLS 8.4.7.
If a method is declared to have a return type, then a compile-time
error occurs if the body of the method can complete normally.
In other words, a method with a return type must return only by using
a return statement that provides a value return; it is not allowed to
"drop off the end of its body".
The compiler looks to see whether normal termination is possible based on the rules defined in JLS 14.21 Unreachable Statements as it also defines the rules for normal completion.
Notably, the rules for unreachable statements make a special case just for loops that have a defined true constant expression:
A while statement can complete normally iff at least one of the
following is true:
The while statement is reachable and the condition expression is not a
constant expression (§15.28) with value true.
There is a reachable break statement that exits the while statement.
So if the while statement can complete normally, then a return statement below it is necessary since the code is deemed reachable, and any while loop without a reachable break statement or constant true expression is considered able to complete normally.
These rules mean that your while statement with a constant true expression and without a break is never considered to complete normally, and so any code below it is never considered to be reachable. The end of the method is below the loop, and since everything below the loop is unreachable, so is the end of the method, and thus the method cannot possibly complete normally (which is what the complier looks for).
if statements, on the other hand, do not have the special exemption regarding constant expressions that are afforded to loops.
Compare:
// I have a compiler error!
public boolean testReturn()
{
final boolean condition = true;
if (condition) return true;
}
With:
// I compile just fine!
public boolean testReturn()
{
final boolean condition = true;
while (condition)
{
return true;
}
}
The reason for the distinction is quite interesting, and is due to the desire to allow for conditional compilation flags that do not cause compiler errors (from the JLS):
One might expect the if statement to be handled in the following
manner:
An if-then statement can complete normally iff at least one of the
following is true:
The if-then statement is reachable and the condition expression is not
a constant expression whose value is true.
The then-statement can complete normally.
The then-statement is reachable iff the if-then statement is reachable
and the condition expression is not a constant expression whose value
is false.
An if-then-else statement can complete normally iff the then-statement
can complete normally or the else-statement can complete normally.
The then-statement is reachable iff the if-then-else statement is
reachable and the condition expression is not a constant expression
whose value is false.
The else-statement is reachable iff the if-then-else statement is
reachable and the condition expression is not a constant expression
whose value is true.
This approach would be consistent with the treatment of other control
structures. However, in order to allow the if statement to be used
conveniently for "conditional compilation" purposes, the actual rules
differ.
As an example, the following statement results in a compile-time
error:
while (false) { x=3; } because the statement x=3; is not reachable;
but the superficially similar case:
if (false) { x=3; } does not result in a compile-time error. An
optimizing compiler may realize that the statement x=3; will never be
executed and may choose to omit the code for that statement from the
generated class file, but the statement x=3; is not regarded as
"unreachable" in the technical sense specified here.
The rationale for this differing treatment is to allow programmers to
define "flag variables" such as:
static final boolean DEBUG = false; and then write code such as:
if (DEBUG) { x=3; } The idea is that it should be possible to change
the value of DEBUG from false to true or from true to false and then
compile the code correctly with no other changes to the program text.
Why does the conditional break statement result in a compiler error?
As quoted in the loop reachability rules, a while loop can also complete normally if it contains a reachable break statement. Since the rules for the reachability of an if statement's then clause do not take the condition of the if into consideration at all, such a conditional if statement's then clause is always considered reachable.
If the break is reachable, then the code after the loop is once again also considered reachable. Since there is no reachable code that results in abrupt termination after the loop, the method is then considered able to complete normally, and so the compiler flags it as an error.

Does Java recognize infinite loops?

Given the following code sample:
public class WeirdStuff {
public static int doSomething() {
while(true);
}
public static void main(String[] args) {
doSomething();
}
}
This is a valid Java program, although the method doSomething() should return an int but never does. If you run it, it will end in an infinite loop. If you put the argument of the while loop in a separate variable (e.g. boolean bool = true) the compiler will tell you to return an int in this method.
So my question is: is this somewhere in the Java specification and are there situation where this behavior might be useful?
I'll just quote the Java Language Specification, as it's rather clear on this:
This section is devoted to a precise explanation of the word "reachable." The idea is that there must be some possible execution path from the beginning of the constructor, method, instance initializer or static initializer that contains the statement to the statement itself. The analysis takes into account the structure of statements. Except for the special treatment of while, do, and for statements whose condition expression has the constant value true, the values of expressions are not taken into account in the flow analysis.
...
A while statement can complete normally iff at least one of the following is true:
The while statement is reachable and the condition expression is not a constant expression with value true.
There is a reachable break statement that exits the while statement.
...
Every other statement S in a nonempty block that is not a switch block is reachable iff the statement preceding S can complete normally.
And then apply the above definitions to this:
If a method is declared to have a return type, then every return statement (§14.17) in its body must have an Expression. A compile-time error occurs if the body of the method can complete normally (§14.1).
In other words, a method with a return type must return only by using a return statement that provides a value return; it is not allowed to "drop off the end of its body."
Note that it is possible for a method to have a declared return type and yet contain no return statements. Here is one example:
class DizzyDean {
int pitch() { throw new RuntimeException("90 mph?!"); }
}
Java specification defines a concept called Unreachable statements. You are not allowed to have an unreachable statement in your code (it's a compile time error). A while(true); statement makes the following statements unreachable by definition. You are not even allowed to have a return statement after the while(true); statement in Java. Note that while Halting problem is undecidable in generic case, the definition of Unreachable Statement is more strict than just halting. It's deciding very specific cases where a program definitely does not halt. The compiler is theoretically not able to detect all infinite loops and unreachable statements but it has to detect specific cases defined in the spec.
If you are asking if infinite loops can be useful, the answer is yes. There are plenty of situations where you want something running forever, though the loop will usually be terminated at some point.
As to your question: "Can java recognized when a loop will be infinite?" The answer is that it is impossible for a computer to have an algorithm to determine if a program will run forever or not. Read about: Halting Problem
Reading a bit more, your question is also asking why the doSomething() function does not complain that it is not returning an int.
Interestingly the following source does NOT compile.
public class test {
public static int doSomething() {
//while(true);
boolean test=true;
while(test){
}
}
public static void main(String[] args) {
doSomething();
}
}
This indicates to me that, as the wiki page on the halting problem suggests, it is impossible for there to be an algorithm to determine if every problem will terminate, but this does not mean someone hasn't added the simple case:
while(true);
to the java spec. My example above is a little more complicated, so Java can't have it remembered as an infinite loop. Truely, this is a weird edge case, but it's there just to make things compile. Maybe someone will try other combinations.
EDIT: not an issue with unreachable code.
import java.util.*;
public class test {
public static int doSomething() {
//while(true);
while(true){
System.out.println("Hello");
}
}
public static void main(String[] args) {
doSomething();
}
}
The above works, so the while(true); isn't being ignored by the compiler as unreachable, otherwise it would throw a compile time error!
Yes, you can see these 'infinite' loops in some threads, for example server threads that listen on a certain port for incoming messages.
So my question is: is this somewhere in the Java specification
The program is legal Java according to the specification. The JLS (and Java compiler) recognize that the method cannot return, and therefore no return statement is required. Indeed, if you added a return statement after the loop, the Java compiler would give you a compilation error because the return statement would be unreachable code.
and are there situation where this behavior might be useful?
I don't think so, except possibly in obscure unit tests.
I occasionally write methods that will never return (normally), but putting the current thread into an uninterruptible infinite busy-loop rarely makes any sense.
After rereading the question....
Java understands while(true); can never actually complete, it does not trace the following code completely.
boolean moo = true;
while (moo);
Is this useful? Doubtful.
You might be implementing a general interface such that, even though the method may exit with a meaningful return value, your particular implementation is a useful infinite loop (for example, a network server) which never has a situation where it should exit, i.e. trigger whatever action returning a value means.
Also, regarding code like boolean x = true; while (x);, this will compile given a final modifier on x. I don't know offhand but I would imagine this is Java's choice of reasonable straightforward constant expression analysis (which needs to be defined straightforwardly since, due to this rejection of programs dependent on it, it is part of the language definition).
Some notes about unreachable statements:
In java2 specs the description of 'unreachable statement' could be found. Especially interesting the following sentence:
Except for the special treatment of while, do, and for statements whose condition expression has the constant value true, the values of expressions are not taken into account in the flow analysis.
So, it is not obviously possible to exit from while (true); infinite loop. However, there were two more options: change cached values or hack directly into class file or JVM operating memory space.

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