If have the following code I correctly get an warning in eclipse at the else if code :
final int x = 8;
if (x < 10) {
System.out.println(x);
} else if (x < 5) {
System.out.println(x);
}
But I don't get any warning if I replace the line
final int x = 8;
with
final int x = getX();
getX() is defined somewhere.
What is the reason for this?
JVM knows that x always would be less than 10 in compile-time, but if you replace x declaration
final int x = getX();
JVM will know x value to compare only in runtime
Related questions:
Unreachable code error vs. dead code warning in Java under Eclipse?
final int x = 8;
if (x < 10) {
System.out.println(x);
} else if (x < 5) {
System.out.println();
}
Here you declared value as 8.
so if will execute.There is no possibility to execute else.
But in second case first we dont know the value.In runtime only it know.
if you write final int x = 8; the compiler knows for sure that x < 10 and the if branch is always executed, while in the second case it cannot know the value returned by the called function.
At compile time, the compile know that x will always be 8. But if you use a function, it doesn't drill down into that.
A final primitive is a compile time constant, so it can do the unreachable code check when compiling. In this case, the compiler knows x = 8 and can determine the results of the if statement accordingly.
For the getX() approach, it won't do that check at compile time. This means you won't see that warning.
if (8 < 10) {
//Executing code
} else {
if (8 < 5) {
//Alternative code
}
}
I believe this is the essential equivalent of how your code is read by the compiler (someone with more knowledge than I may be able to correct me. Scratch that, I'm certain they can correct me).
With that said if you look at the logical sequence of your steps, you'll see that the compiler has already determined the steps of execution and can determine that the second if is never satisfied. If you use getX() alternatively though the compiler cannot make those assumptions.
If this holds
x<5
Then this also holds
x<10.
Therefore, the second part will never execute even the value in x is unknown.
Related
I could find similar questions to this, but I could not find the answer that I expect to this particular case.
public int getIndex(){
for(int x = 0; x < 5; x++) {
return x;
}
}
When I execute this code, I got a compilation error saying "Missing return statement". But, as per my knowledge, it is very clear that the code within the for loop will execute without any doubts due to the first time, x=0. So, there is no case not to execute the code inside the for loop for this particular case.
So, why do we need to declare an extra return statement outside the for loop also?.
Unlike you, the compiler is unable to (or rather, does not try to) determine that the loop executes at least once.
The specific rules around this are given in JLS 14.21. In particular:
A basic for statement can complete normally iff at least one of the following is true:
The for statement is reachable, there is a condition expression, and the condition expression is not a constant expression (§15.28) with value true.
There is a reachable break statement that exits the for statement.
The contained statement is reachable iff the for statement is reachable and the condition expression is not a constant expression whose value is false.
You don't have a constant condition expression, so, the compiler considers that such a for loop can complete normally, hence the statements after it are reachable.
It would work without a further return statement if the i < 5 were a constant expression, such as true.
public int getIndex(){
for(int x = 0; true; x++) {
return x;
}
}
The compiler could determine that your original loop never completed normally, given far more complicated rules about reachability, but the practical use cases of this are so small that it would not justify the complexity.
This is because JVM have no idea about conditional break you will use inside the loop. For example :
public static int getIndex(){
for(int x=0; x<5;x++){
if(x<5) continue;
return x;
}
return 6;
}
Here it's clear that without a return outside the loop you could miss return statement inside loop
I suggest that your example isn't real, But you can change it to do-while without compilation errors:
public static int getIndex() {
int x = 0;
do {
return x++;
} while (x < 5);
}
in your function
- This method must return a result of type int
error generation
bcz
public static int getIndex(){
for(int x = 0; x < 5; x++) {
return x;
}
}
not have specify return value out side function
Default return
public static int getIndex(){
for(int x = 0; x < 5; x++) {
return x;
}
return 0; <---------
}
These conditions are not understandable at compile time, whereas at runtime they are understood by JVM. But for the code to compile it requires a return statement outside the for-loop. So to get the code compiled, you must have a return statement theoretically.
I'm trying to write a Java program to calculate the square root of an integer x, without using in-built functions like Math.pow() . This is the approach I tried -
class Solution {
public int mySqrt(int x) {
if(x==0 || x==1)
return x;
// if(x>=2147395600)
// return 46340;
int i;
for(i=1 ; i*i<=x ; i++) {}
return i-1;
}
}
Without the commented part, I start getting errors if x is in the range 2147395600 <= x <= 2^31-1 (which is the upper limit of an int's value range in Java). For instance, for the input x=2147395600, the expected output is 46340 but the actual output is 289398. Why is this happening? Thanks to all in advance.
PS - I am aware there are other (better) methods to solve this problem, but I'd really like to know why this code behaves this way.
Since 46340 * 46340 = 2147395600, when i=46340, x=2147395600 and you reach the condition i*i<=x it evaluates to true since 2147395600 = 2147395600. So the loop counter will incremnet by 1 and in the next iteration we will get i=46341 and i * i will cause an overflow - 46341*46341 = -2147479015.
The loop condition will still be true, since -2147479015 <= 2147395600, and the loop will not stop.
You can replace the <= with =, and check for edge cases that may occur now.
I could find similar questions to this, but I could not find the answer that I expect to this particular case.
public int getIndex(){
for(int x = 0; x < 5; x++) {
return x;
}
}
When I execute this code, I got a compilation error saying "Missing return statement". But, as per my knowledge, it is very clear that the code within the for loop will execute without any doubts due to the first time, x=0. So, there is no case not to execute the code inside the for loop for this particular case.
So, why do we need to declare an extra return statement outside the for loop also?.
Unlike you, the compiler is unable to (or rather, does not try to) determine that the loop executes at least once.
The specific rules around this are given in JLS 14.21. In particular:
A basic for statement can complete normally iff at least one of the following is true:
The for statement is reachable, there is a condition expression, and the condition expression is not a constant expression (§15.28) with value true.
There is a reachable break statement that exits the for statement.
The contained statement is reachable iff the for statement is reachable and the condition expression is not a constant expression whose value is false.
You don't have a constant condition expression, so, the compiler considers that such a for loop can complete normally, hence the statements after it are reachable.
It would work without a further return statement if the i < 5 were a constant expression, such as true.
public int getIndex(){
for(int x = 0; true; x++) {
return x;
}
}
The compiler could determine that your original loop never completed normally, given far more complicated rules about reachability, but the practical use cases of this are so small that it would not justify the complexity.
This is because JVM have no idea about conditional break you will use inside the loop. For example :
public static int getIndex(){
for(int x=0; x<5;x++){
if(x<5) continue;
return x;
}
return 6;
}
Here it's clear that without a return outside the loop you could miss return statement inside loop
I suggest that your example isn't real, But you can change it to do-while without compilation errors:
public static int getIndex() {
int x = 0;
do {
return x++;
} while (x < 5);
}
in your function
- This method must return a result of type int
error generation
bcz
public static int getIndex(){
for(int x = 0; x < 5; x++) {
return x;
}
}
not have specify return value out side function
Default return
public static int getIndex(){
for(int x = 0; x < 5; x++) {
return x;
}
return 0; <---------
}
These conditions are not understandable at compile time, whereas at runtime they are understood by JVM. But for the code to compile it requires a return statement outside the for-loop. So to get the code compiled, you must have a return statement theoretically.
private static void convert(int x) {
// assume we've passed in x=640.
final int y = (x + 64 + 127) & (~127);
// as expected, y = 768
final int c = y;
// c is now 320?!
}
Are there any sane explanations for why the above code would produce the values above? This method is called from JNI. The x that is passed in is originally a C++ int type that is static_cast to a jint like so: static_cast<jint>(x);
In the debugger, with the breakpoint set on the y assignment, I see x=640. Stepping one line, I see y=768. Stepping another line and c=320. Using the debugger, I can set the variable c = y and it will correctly assign it 768.
This code is single threaded and runs many times per second and the same result is always observed.
Update from comments below
This problem has now disappeared entirely after a day of debugging it. I'd blame it on cosmic rays if it didn't happen reproducibly for an entire day. Oddest thing I've seen in a very long time.
I'll leave this question open for a while in case someone has some insight on what could possibly cause this.
Step 01: compile it right, see comments under your post.
if needed i with this code it will go:
C# Code:
private void callConvert(object sender, EventArgs e)
{
string myString = Convert.ToString(convert123(640));
textBox1.Text = myString;
}
private static int convert123(int x) {
// assume we've passed in x=640.
int y = (x + 64 + 127) & (~127);
// as expected, y = 768
int c = y;
// c is now 320?!
return (c);
}
but its a c# code
and a tipp for you NEVER call your funktion with a name that is used in the compiler as an standart.
convert is in the most langues used.
(system.convert)
Have you set c to 320 recently? If so, it may have been stored in some memory and the compiler may have reassigned it to what it thought it was and not what it should be. I am, in part, guessing though.
It looks like problem of memory byte size of temporary variables if program is optimized for memory usage. Debugger may not be reliable. I see if the temporary ~127 is store in a byte, then you may reach at the scenario you observed. It all depends on what is ~127 is stored in at run time.
(In the process of writing my original question, I answered it, but the information might be useful to others, and I thought of a new question)
For instance:
int x;
if (x = 5) { ... }
Creates an error:
Type mismatch: cannot convert from int to boolean. (Because assignment doesn't return a
boolean value)
However,
int x;
if ((x = 5) == 5) {
System.out.println("hi!");
}
will print out "hi!"
And similarly,
String myString = "";
if ((myString = "cheese").equals("cheese")) {
System.out.println(myString);
}
prints out "cheese"
Sadly,
if ((int x = 5) > 2) { ... }
does not work with an in-line declaration. How come? Can I get around this?
Sadly,
I suspect that most Java developers would heartily disagree with that sentiment ...
if ((int x = 5) > 2) { ... }
does not work with an in-line
declaration. How come?
It does not work because a declaration is not a Java expression, and cannot be used in an Java expression.
Why did the Java designers not allow this? I suspect that it is a combination of the following:
Java's syntactic origins are c and C++, and you cannot do this in C or C++ either,
this would make the Java grammar more complicated and the syntax harder to understand,
this would make it easier to write obscure / cryptic programs in Java, which goes against the design goals, and
it is unnecessary, since you can trivially do the same thing in simpler ways. For instance, your example can be rewriten this to make the declaration of x to a separate statement.
Can I get around this?
Not without declaring x in a preceding statement; see above.
(For what it is worth, most Java developers avoid using assignments as expressions. You rarely see code like this:
int x = ...;
...
if ((x = computation()) > 2) {
...
}
Java culture is to favour clear / simple code over clever hacks aimed at expressing something in the smallest number of lines of code.)
Your x only exists within the scope of the assignment, so it's already gone by the time you get to > 2. What is the point of this anyway? Are you trying to write deliberately unreadable code?
Your best way to get around this is to declare x in a scope that will remain valid throughout the if statement. Seriously though, I fail to understand what you're doing here. Why are you creating a variable that is supposed to disappear again immediately?
if ((int x = 5) > 2) { ... }
Yes this will not compile because you can't declare variables inside the condition section of if clause
The > test will work fine, as long as you declare the int outside of the if condition. Perhaps you are simplifying your condition for the sake of brevity, but there is no reason to put your declaration in the condition.
Can I get around this?
Yes, declare your var outside the condition.
Because you didn't declare the int separately as you did in the == test.
jcomeau#intrepid:/tmp$ cat /tmp/test.java
class test {
public static void main(String[] args) {
int x;
if ((x = 5) > 2) System.out.println("OK");
}
}
In Java, for() allows initialization code, but if() doesn't.
You can't declare the variable in condition section. For example
for(int i = 0; j < 9; i++){...}
is completely valid statement. Notice we declare the variable in for but not in a condition clause, now look at this,
for(int i = 0; (int j = 0)<9; i++){...} // Don't try to make logical sense out of it
not allowed.