class string1 {
static public void main(String[] ar) {
String s1 = "test";
String s2 = new String();
if(s2=null) { // line 0
System.out.println(s1);
System.out.println(s2.length()); //Line 1
}
}
}
What i expected to happen was
a) s2 will be set to null because its an assignment operation as I am not using ==
b) And I will get a NPE at Line 1 during Runtime
and instead I got the following output as shown below.
Output is
if(s2=null)
^
required: boolean
found: String
1 error
Can someone explain why I am getting compile error ?
Java will not implicitly cast to a boolean like some languages will. You must put an expression that evaluates to a boolean inside of conditional:
if ((s2 = null) != null) { }
This condition of course makes no sense, but it's the equivalent of what you're attempting to do. It's worth noting by the way that assignments should rarely be done in a condition.
You should do like this:
if( (s2 = null) != null)
{
// do stuff
}
The reason you are getting this error because you have to explicitly put the code for boolean evaluation in conditions as Java doesn't implicitly cast it boolean.
The if condition evaluates only boolean conditions.
And the assignment operator does not give a boolean result here.
That is the reason for getting exception.
If you use if ((s2 = null) != null) instead of if(s2=null) it will work.
You should note the fact that in java there are only two boolean values : true and false unlike some other languages which use 0 as false and anything else as true .
Can someone explain why I am getting compile error ?
In an if statement the condition can either be true or false which are returned by comparison operations and by the boolean variables.
In,
if(s2=null)
the s2=null doesn't evaluate to any boolean value i.e, true or false therefore the compiler error :
required: boolean
found: String
An if-then statement is executed by first evaluating the Expression.
From, JLS - Chapter14 : Blocks and Statements
14.9.1. The if-then Statement
An if-then statement is executed by first evaluating the Expression.
If the result is of type Boolean, it is subject to unboxing
conversion (ยง5.1.8).
If evaluation of the Expression or the subsequent unboxing conversion
(if any) completes abruptly for some reason, the if-then statement
completes abruptly for the same reason.
Otherwise, execution continues by making a choice based on the
resulting value:
If the value is true, then the contained Statement is executed; the
if-then statement completes normally if and only if execution of the
Statement completes normally.
If the value is false, no further action is taken and the if-then statement completes normally.
Besides what everyone else said, s2 will never be null - you just assigned a new String to it! Are you sure you're not conflating string length/existence tests from other languages?
Related
I'm curious is it possible to call a method that returns a boolean value in the condition part of a while loop?
As in:
while(someMethod()!= true){
//Do stuff
}
And the method simply returns a true or false. Is this possible or not and if so is there a correct syntax or a better way?
Edit: Thanks for the quick responses. As an extension to my question is it possible to call the method multiple times for different things but require them all to be the same before exiting the loop?
For example:
while(!(someMethod(input_a) == someMethod(input_b))){
//Do stuff
}
Where both of the returned values are the returned values are equal?
Hope this will help you
public boolean functionOne(int i){
// some operation
if(i == 1) return true;
else return false;
}
public void otherFunc(){
int i = 0;
if(functionOne(i)) { // e.g: if(functionOne(i) == true)
// your code
// 0!=1 so result is fort
}
if(!functionOne(i)){ // e.g: if(functionOne(i) == false)
// your code
// 0!=1 it is false, but ! before functionOne negate so ! of false is true
}
// **for your while**
while(functionOne(i)){ // while function returns true
// code
}
// **or**
while(!functionOne(i)){ // while function returns false
// code
}
}
Yes of course!
public static boolean someMethod(){
return false;
}
public static void main(String[] args){
while(!someMethod()){
//do something
System.out.println("Hi");
}
}
Like in this code, an infinite loop will be called if the method returns false, but if the method returns true, it will just come out of the while loop. :)
Less is best:
while (!someMethod()) {
// Do stuff
}
It's never a good idea to compare to a boolean result to a boolean literal. Prefer using the result in-line, using the logical unary not operator ! as required.
Answering the now-edited version of the question, less is still best:
while (someMethod(input_a) != someMethod(input_b))
You can find the specification of the while loop in JLS Sec 14.12:
The while statement executes an Expression and a Statement repeatedly until the value of the Expression is false.
WhileStatement:
while ( Expression ) Statement
WhileStatementNoShortIf:
while ( Expression ) StatementNoShortIf
The Expression must have type boolean or Boolean, or a compile-time error occurs.
So, you can use anything which is an Expression of type boolean (or Boolean).
And if you click through the productions in the language spec:
Expression, contains
AssignmentExpression, contains
ConditionalExpression, contains
ConditionalOrExpression, contains
ConditionalAndExpression, contains
InclusiveOrExpression, contains
ExclusiveOrExpression, contains
AndExpression, contains
EqualityExpression, contains
RelationalExpression, contains
ShiftExpression, contains
AdditiveExpression, contains
MultiplicativeExpression, contains
UnaryExpression, contains
UnaryExpressionNotPlusMinus, contains
PostfixExpression, contains
Primary, contains
PrimaryNoNewArray, contains
MethodInvocation
Phew! That's pretty deeply buried! (You can read this like an inheritance hierarchy, so every MethodInvocation is a PrimaryNoNewArray, and every PrimaryNoNewArray is a Primary etc).
So, transitively, every MethodInvocation is an Expression, hence it's fine to use it as the expression in a while loop.
Addressing your edit: yes, that's fine too. If you look at the detail of the EqualityExpression:
EqualityExpression:
RelationalExpression
EqualityExpression == RelationalExpression
EqualityExpression != RelationalExpression
As already described above, you can use an EqualityExpression as the Expression in a WhileStatement. And something of the form
RelationalExpression != RelationalExpression
is an EqualityExpression by the rule shown. Since all MethodInvocations are RelationalExpressions, you can use method invocations in the while statement as you've shown:
while(someMethod(input_a) != someMethod(input_b)) {
(a != b is an easier way of writing !(a == b)).
This is the way we have done loops over java iterators. For instance:
Iterator[String] iterator = util.Arrays.asList("One", "Two", "Three").iterator();
while(iterator.hasNext()) {
println(iterator.next());
}
We have also done something similar for the JDBC ResultSet interface.
Can someone please explain what this line of java code is doing?
public String getTitleNavContainer(boolean isThisLandingPage) {
return isThisLandingPage ? StringUtils.EMPTY : "title-nav-container";
}
I can see what it is doing but I am wondering how I would modify this so that if it is landing page it does one thing otherwise do something else.
Thanks for your help.
return isThisLandingPage ? StringUtils.EMPTY : "title-nav-container";
is the same as:
public String getTitleNavContainer(boolean isThisLandingPage) {
if ( isThisLandingPage ){
return StringUtils.EMPTY;
}
else{
return "title-nav-container";
}
}
It's just a shorter way to write it, making the code easier to read.
The above line is called ternary operator
Ternary Operator takes three parameter and its sudo code is
condition ? statement1 : statement2
Condition: This part should have valid conditional statement and that should return only boolean value
Statement1: If condition is true then statement1 will execute
Statement2: If condition is false then statement2 will execute
Now look at your code block
public String getTitleNavContainer(boolean isThisLandingPage) {
return isThisLandingPage ? StringUtils.EMPTY : "title-nav-container";
}
if isThisLandingPage is true then StringUtils.EMPTY will execute else title-nav-container execute
For quick understanding, convert the code as if-else statement
if (isThisLandingPage)
{
return StringUtils.EMPTY;
}
else
{
return title-nav-container;
}
You are using the ternary operator (or the conditional operator) is an alternative to the Java if/then/else syntax, but it goes beyond that, and can even be used on the right hand side of Java statements.
Basically it evaluates the predicate
;(boolean expression) (if it is true) (if it is false)
isThisLandingPage ? StringUtils.EMPTY : "title-nav-container";
And this expression returns that value depending on the boolean expression, this value is the one that the function returns the Empty String "" from this class doc or the String "title-nav-container".
I hope this help you
Why this code is wrong ? When I change "else if(this.power >= p)" into only "else", it's right. Can anybody give me a hint?
public boolean useBattery(double p) {
if(this.power < p) {
this.power = 0.0;
return false;
} else if(this.power >= p) {
this.power = this.power - p;
return true;
}
}
To a human reader looking at the code it seems that either the first return will be hit, or the second, but the compiler can't be sure. To the compiler it looks like:
if (condition1) {
...
return false;
} else if (condition2) {
...
return true;
}
and it needs to know, what will the method return if neither condition1 nor condition2 is true?
Whereas if you change it to a straight else,
if (condition1) {
...
return false;
} else {
...
return true;
}
then it is certain that one of the two return statements must be hit.
In fact in your method there is a chance that neither condition will be met: if one of the numbers you are comparing is NaN (the special floating point value representing "not a number"), then both of your if conditions will be false, and the method would have no return value.
There is also theoretically a possibility that some code running in another thread might alter the value of this.power between the first if check and the second, which could lead to both conditions evaluating to false. So it is not possible for the compiler to know for certain that one of the conditions will be met, even if they were logically complementary.
What happens if we don't enter any of your conditional branches? Java can't determine that you'll be able to because else if implies that there may not be another conditional branch to check.
Phrased another way, there's an implicit else block that does nothing. Since you declare a return type, having this implicit else block do nothing is an error.
An else block is always guaranteed to execute, so you will not run into the same situation with else, which is probably what you intended to use in the first place.
Think in the case of a flowchart.
If (this.power < p), then
Set power to 0
Return false
Else if (this.power >= p), then
Subtract p from power
Return true
Else (implied)
Do nothing <- this is the error
Because if you add if into the second else there might be a condition where neither of the condition will be satisfied and method will match to no return statement.
Consider this simple example:
Consider x=5; below code will match no return statement because it doesn't satisfies any condition.
if(x>5){
return true;
}
else if(x < 5){
return false;
}
You can reproduce this error with even shorter code:
public int doSomething() {
if(true) {
return 0;
}
}
This method generates compiler error missing return statement
Compiler doesn't perform intelligent static analysis of your code. It just checks statements according to specification.
Java Language Specification 8.4.7 "Method body" states that:
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.
So, compiler just checks if these statements can complete normally.
JLS 14.9.1 "The if-then Statement":
If the value is true, then the contained Statement is executed; the if-then statement completes normally if and only if execution of the Statement completes normally.
If the value is false, no further action is taken and the if-then statement completes normally.
As you can see by specification if statement can complete normally. That's why a compile-time error occurs.
On the other hand, by JLS 14.9.2 "The if-then-else Statement":
If the value is true, then the first contained Statement (the one before the else keyword) is executed; the if-then-else statement completes normally if and only if execution of that statement completes normally.
If the value is false, then the second contained Statement (the one after the else keyword) is executed; the if-then-else statement completes normally if and only if execution of that statement completes normally.
As you can see if-then-else completes if and only if one of its blocks completes normally. In your example both of them contain return statements.
Netbeans gives me The conditional statement is redundant warning for this:
return (this.getId(person) == null) ? false : true;
And if I comply with that, it changes to this:
return (this.getId(person) != null);
Are these two equal? How is the second one conditional?
Yes , They both are conceptually same.
The second one is not conditional. Its an expression resolves into boolean, So simply you can result of that expression.
Why it is redundant in first case is , It's just like writing
if(true){
return true;
}else{
return false;
}
Look at your condition
this.getId(person) != null;
your this.getId(person) may be null or may not. So that expression resolves as true or false . That's it. Right ? So your IDE is telling that use that expression result.
You can unwrap the first form to something like this:
boolean cnd = (this.getId(person) == null);
if (cnd)
return true;
else
return false;
This clearly shows that switching on a boolean value just to return the same boolean value is redundant.
The second statement is not conditional but it provides the same result with fewer hops.
The expression this.getId(person) == null will return you true or false. Again adding a ternary operator is redundant.
You are returning a boolean value and
return (this.getId(person) != null);
is a boolean conditional statement that will evaluate to true or false. This is why the compiler is telling you that the conditional statement is redundant. It will still compile the other way but its more typing and it's not as clean.
When I'm compiling this code
public static void main(String [] args) {
int x = 0;
while(false)
{
System.out.println(hello);
}
}
it is showing compile time error unreachable code.
But when I modified this code to
public static void main(String [] args) {
int x = 0;
boolean result = false;
while(result)
{
x=4;
}
}
it's working fine.
Can somebody tell me the reason behind this behavior.
It is because boolean result = false is not a constant expression whereas false is. If you try the code below, it won't compile either because result is now a constant:
final boolean result = false;
while(result) { x=4; }
However this would compile, because result is not a constant variable any longer:
final boolean result;
result = false;
while(result) { x=4; }
See also: Why does the Java compiler not understand this variable is always initialized? for a similar discussion.
Usage of constant false in the following statement
while(false)
is resolved to false at compilation time hence compiler complains for unreachable code.
But when you use a variable instead:
boolean result = false;
while(result)
compiler is not sure about the value of it at compile time and hence does not complain.
The behavior of the compiler is precisely specified in the Java Language Specification, Section 14.21. Unreachable Statements.
Here is a key quote, which directly addresses your question:
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.
Java uses a simple flow analysis algorithm to find most common cases of unreachable code, and all such unreachable code blocks will be flagged as compile-time errors. That's why your "while (false) { ... }" statement produces an error.