final keyword in condition section of for loop - java

A.
int a=10,b=20;
for(int i=0;a>b;i++)
{
System.out.print("aa");
}
System.out.print("bb");
B.
final int a=10,b=20;
for(int i=0;a>b;i++)
{
System.out.print("aa");
}
System.out.print("bb");
Q. why code A prints an output "bb" while code B returns an error "unreachable code"?

final int a=10,b=20;
means the variables will never Change its values after compiled
therefore this for Loop
for(int i=0;a>b;i++)
has a never breaking condition (a>b will never be true), therefore the Loop is forever and this becomes
System.out.print("bb");
"unreachable code"

On the Section A code can be changed like below and print both outputs. Note that while execute on the loop it's possible to change the value on a and b. and output will be aabb
int a=10,b=20;
for(a=30;a>b;)
{
System.out.print("aa");
a=a-20;
}
System.out.print("bb");
In section B on the run time it's not possible to change the values of a or b since those are Final variable. Due to that reason JVM can identify that there is no possibility of a>b condition getting true. (Since a>b always false).
So JVM will throw compilation error saying Unreachable code.

final key word says that a and b values cannot be changed i.e. they are values and not variables and therefore for loop will never execute inner statement, so the compiler deduces that the code inside for loop is unreachable.

B returns an error "unreachable code"
for(int i=0;a>b;i++) //with final modifier, `a` & `b` are constants
How compiler sees your code with final modifier, that's compiler complains about
for(int i=0;10>20;i++)
10 will be always less than 20, so your body of loop in unreachable code

Related

Why is a local variable in Java not considered "effectively final" even though nothing modifies it afterwards?

In a method I have this:
int x = 0
if (isA()) {
x = 1;
} else if (isB()) {
x = 2;
}
if (x != 0) {
doLater(() -> showErrorMessage(x)); // compile error here
}
// no more reference to 'x' here
I don't understand why it produces compilation error. The error says that x is not final or effectively-final, so it can't be accessed from the lambda body. There is no modification to x after the doLater call, so the value of x is actually already determined when doLater is called.
I am guessing that the answer to this question is because x is not qualified to be called an effectively-final variable. However, I want to know what the reason is.
Can't the compiler just create a temporary final variable, effectively making the code like:
if (x != 0) {
final int final_x = x;
doLater(() -> showErrorMessage(final_x));
}
and everything still work the same?
Effectively final means that it could have been made final i.e. it never changes. It means that effectively, the variable could be a final one.
The problem is that it doesn't keep track of the last time you changed it, but rather, did you ever change it. Change your if statement to
int x;
if (isA()) {
x = 1;
} else if (isB()) {
x = 2;
} else {
x = 0;
}
or
int x = isA() ? 1 :
isB() ? 2 : 0;
Your x variable would have been effectively final it it was initialized once and not changed again under any circumstances. If you had only:
int x = 0;
doLater(() -> showErrorMessage(x));
then it would have compiled.
However, adding conditions that might change the variable's value
int x = 0;
if (isA()) {
x = 1;
} else if (isB()) {
x = 2;
}
makes the variable being not effectively final and thus the compile error is risen.
Additionally, since this pointer approach you've implemented wouldn't work, you could refactor your code a bit to a simple if-else statement:
if (isA()) {
doLater(() -> showErrorMessage(1));
} else if (isB()) {
doLater(() -> showErrorMessage(2));
}
and completely get rid of x.
Short version, a variable is effectively final if it is assigned exactly once, no matter which code path is executed.
Long version, quoting Java Language Specification 4.12.4. final Variables (emphasis mine):
Certain variables that are not declared final are instead considered effectively final:
A local variable whose declarator has an initializer (§14.4.2) is effectively final if all of the following are true:
It is not declared final.
It never occurs as the left hand side in an assignment expression (§15.26). (Note that the local variable declarator containing the initializer is not an assignment expression.)
It never occurs as the operand of a prefix or postfix increment or decrement operator (§15.14, §15.15).
Now, you can make it effectively final by removing the initializer, because it continues:
A local variable whose declarator lacks an initializer is effectively final if all of the following are true:
It is not declared final.
Whenever it occurs as the left hand side in an assignment expression, it is definitely unassigned and not definitely assigned before the assignment; that is, it is definitely unassigned and not definitely assigned after the right hand side of the assignment expression (§16 (Definite Assignment)).
It never occurs as the operand of a prefix or postfix increment or decrement operator.

Variable not seemed to be initialized

import java.util.Scanner;
public class finnTall {
public static void main(String[]args){
int antallTall;
int antallLest;
double nesteTall;
double minsteVerdi;
double nestMinsteVerdi;
Scanner tast = new Scanner(System.in);
System.out.println("Hvor mange tall?");
antallTall = tast.nextInt();
tast.nextLine();
antallLest= 1;
System.out.println("Skriv første tall: ");
minsteVerdi = tast.nextDouble();
tast.nextLine();
for(antallLest=1;antallTall>antallLest;antallLest++){
System.out.printf("Skriv %d. tall: ",antallLest+1);
nesteTall = tast.nextDouble();
tast.nextLine();
if(nesteTall>minsteVerdi)
nestMinsteVerdi=nesteTall;
if(nesteTall<minsteVerdi)
nesteTall = minsteVerdi;
if(nesteTall>minsteVerdi && nesteTall<nestMinsteVerdi)
nestMinsteVerdi = nesteTall;
}
System.out.printf("Minste verdien av tallene du har oppgitt er: %f\n",minsteVerdi);
System.out.printf("Nest minste verdi av tallene du har oppgitt er: %f\n",nestMinsteVerdi);
tast.close();
}
}
It's a program supposed to calculate the lowest and second lowest number that the user provides.
For some reason, it says that the local variable nestMinsteVerdi is not initialized, and I can't seem to figure out why or where the fault is. I have been struggling with this for a good 2 hours.
Thanks in advance.
In Java, a local variable needs to have a definitely assigned value before its value is accessed.
You declare your local variable without assigning it a value. This is okay in Java, because the compiler will ensure that you give it a value before using it.
double nestMinsteVerdi;
Then set it if a condition is true:
if(nesteTall>minsteVerdi)
nestMinsteVerdi=nesteTall;
Then access it in the conditional of an if statement. But if the condition above were false, the value of nestMinisteVerdi would not yet be assigned.
if(nesteTall>minsteVerdi && nesteTall<nestMinsteVerdi)
nestMinsteVerdi = nesteTall;
Since there's at least one way for the code to execute in which no value is assigned, the compiler complains. This is a good thing. Accidentally uninitialized variables can be a frequent source of defects.
From the Java Language Specification, Chapter 16: Definite Assignment:
The idea behind definite assignment is that an assignment to the local variable or blank final field must occur on every possible execution path to the access.
Andy Thomas's answer is correct. You do not assign a value to the variable.
double nestMinsteVerdi;
The compiler will not allow you to run because the only assignment is within a conditional that could conceivably fail, and if it were to fail, the variable would not be assigned a value. Since code can't be compared to a variable with no value, this would break execution, so the compiler will not allow it.

When would a do-while loop be the better than a while-loop?

This is a highly subjective question, so I'll be more specific. Is there any time that a do-while loop would be a better style of coding than a normal while-loop?
e.g.
int count = 0;
do {
System.out.println("Welcome to Java");
count++;
} while (count < 10);`
It doesn't seem to make sense to me to check the while condition after evaluating the do-statement (aka forcing the do statement to run at least once).
For something simple like my above example, I would imagine that:
int count = 0;
while(count < 10) {
System.out.println("Welcome to Java"); count++;
}
would be generally considered to have been written in a better writing style.
Can anyone provide me a working example of when a do-while loop would be considered the only/best option? Do you have a do-while loop in your code? What role does it play and why did you opt for the do-while loop?
(I've got an inkling feeling that the do-while loop may be of use in coding games. Correct me, game developers, if I am wrong!)
If you want to read data from a network socket until a character sequence is found, you first need to read the data and then check the data for the escape sequence.
do
{
// read data
} while ( /* data is not escape sequence */ );
The while statement continually executes a block of statements while a particular condition is true
while (expression) {
statement(s)
}
do-while evaluates its expression at the bottom of the loop, and therefore, the statements within the do block are always executed at least once.
do {
statement(s)
} while (expression);
Now will talk about functional difference,
while-loops consist of a conditional branch instructions such as if_icmpge or if_icmplt and a goto statement. The conditional instruction branches the execution to the instruction immediately after the loop and therefore terminates the loop if the condition is not met. The final instruction in the loop is a goto that branches the byte code back to the beginning of the loop ensuring the byte code keeps looping until the conditional branch is met.
A Do-while-loops are also very similar to for-loops and while-loops except that they do not require the goto instruction as the conditional branch is the last instruction and is be used to loop back to the beginning
A do-while loop always runs the loop body at least once - it skips the initial condition check. Since it skips first check, one branch will be less and one less condition to be evaluated.
By using do-while you may gain performance if the expression/condition is complex, since it is ensured to loop atleast once. In that casedo-while could call for performance gain
Very Impressive findings here,
http://blog.jamesdbloom.com/JavaCodeToByteCode_PartOne.html#while_loop
The do-while loop is basically an inverted version of the while-loop.
It executes the loop statements unconditionally the first time.
It then evaluates the conditional expression specified before executing the statements again.
int sum = 0;
int i = 0;
do
{
sum += ids[i];
i++;
} while (i < 4);
Reference material
Simply, when you want to check condition before and then perform operation while is better option, and if you want to perform operation at least once and then check the condition do-while is better.
As per your question a working example,
1. when I needed to find the field which could be declared in the same class or the super class or the super class of that super class and so on i.e. finding the field located in deep class hierarchy. (A extends B B extends C and so on)
public Field SearchFieldInHierarchy(Object classObj, String fieldName )
{
Field type = null;
Class clz = classObj.getClass();
do
{
try
{
type = clz.getDeclaredField(fieldName);
break;
} catch (NoSuchFieldException e)
{
clz = clz.getSuperclass();
}
} while(clz != null || clz != Object.class);
return type;
}
2. When reading input stream from Http response
do
{
bytesRead = inputStream.read(buffer, totalBytesRead, buffer.length - totalBytesRead);
totalBytesRead += bytesRead;
} while (totalBytesRead < buffer.length && bytesRead != 0);
You kind of answer the question yourself-when it needs to run at least once, and it makes sense to read it that way.
do - while loop allows you to ensure that the piece of code is executed at least once before it goes into the iteration.
In a while loop, the condition is tested before it executes code in the loop. In a do while loop, the code is executed before the condition is tested, resulting in the code always being executed at least once. Example:
$value = 5;
while($value > 10){
echo "Value is greater than 10";
}
The above would never output anything. If we do the same again like this:
$value = 5;
do{
echo "Value is greater than 10";
}while($value > 10)
It would output Value is greater than 10 because the condition is tested after the loop is executed. After this it would not output anything further.
The difference between do-while and while is that do-while evaluates its expression at the bottom of the loop instead of the top. Therefore, the statements within the do block are always executed at least once.
For example do check this link: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/while.html
If the looping condition can only be known after a first step of the loop (when you do not want a condition before you enter the loop).
Typically:
do {
expr = ...;
while (expr);
Use the while Statement when you have to check a condition repeatedly and only when the condition is satisfied execute the loop
while(condition) //eg. a>5
{
Body of Loop
}
If you see the flow of control here you can see that the condition is checked before the execution of the loop, if the condition is not met the loop will not execute at all
In the Do-While statement the program will execute the body of the loop once and then it will check if the statement is true or not
do
{
Body of Loop
}
while(condition); //eg. a>5
If you notice the flow of control here you will see that the body is executed once, then the condition is checked. If the condition is False the Program will break out of the loop, if True it will continue executing till the condition is not satisfied
It is to be noted that while and do-while give the same output only the flow of control is different
/*
while loop
5 bucks
1 chocolate = 1 bucks
while my money is greater than 1 bucks
select chocolate
pay 1 bucks to the shopkeeper
money = money - 1
end
come to home and cant go to while shop because my money = 0 bucks
*/
#include<stdio.h>
int main(){
int money = 5;
while( money >= 1){
printf("inside the shopk and selecting chocolate\n");
printf("after selecting chocolate paying 1 bucks\n");
money = money - 1 ;
printf("my remaining moeny = %d\n", money);
printf("\n\n");
}
printf("dont have money cant go inside the shop, money = %d", money);
return 0;
}
infinite money
while( codition ){ // condition will always true ....infinite loop
statement(s)
}
please visit this video for better understanding
https://www.youtube.com/watch?v=eqDv2wxDMJ8&t=25s
It is very simple to distinguish between the two. Let's take While loop first.
The syntax of while loop is as follows:
// expression value is available, and its value "matter".
// if true, while block will never be executed.
while(expression) {
// When inside while block, statements are executed, and
// expression is again evaluated to check the condition.
// If the condition is true, the while block is again iterated
// else it exists the while block.
}
Now, let's take the do-while loop.
The syntax of do-while is different:
// expression value is available but "doesn't matter" before this loop, & the
// control starts executing the while block.
do {
// statements are executed, and the
// statements is evaluated and to check the condition. If true
// the while block is iterated, else it exits.
} while(expression);
A sample program is given below to make this concept clear:
public class WhileAndDoWhile {
public static void main(String args[]) {
int i = 10;
System.out.println("While");
while (i >= 1) {
System.out.println(i);
i--;
}
// Here i is already 0, not >= 1.
System.out.println("do-while");
do {
System.out.println(i);
i--;
} while (i >= 1);
}
}
Compile and run this program, and the difference becomes apparent.

Code wont compile because final variable "might" (but can't) be assigned twice?

Have a look at this simple Java code:
class A {
public static void main(String[] args) {
final int x;
try {
throw new RuntimeException();
x = 1;
} finally {}
x = 2;
System.out.println("x: " + x);
}
}
I'd expect it to print "x: 2".
A.java:6: unreachable statement
x = 1;
^
A.java:8: variable x might already have been assigned
x = 2;
^
2 errors
It says it wont compile because on line 8, x = 2 might reassign the final variable, but this is false because as it said above, the line x = 1 is unreachable, thus it will assign it for the first time, not reassign.
Why does the compiler give an error stating that "x might have already been assigned" when it knows that x has not been assigned?
It is explained in the JLS chapter 16
[...] Similarly, every blank final variable must be assigned at most
once; it must be definitely unassigned when an assignment to it
occurs.
Such an assignment is defined to occur if and only if either the
simple name of the variable (or, for a field, its simple name
qualified by this) occurs on the left hand side of an assignment
operator.
For every assignment to a blank final variable, the variable must be
definitely unassigned before the assignment, or a compile-time error
occurs.
So, JLS does not seem to care about unreachable code.
And concerning exceptions it says:
An exception parameter V of a catch clause (§14.20) is definitely
assigned (and moreover is not definitely unassigned) before the body
of the catch clause.
so the problem here is that x=1 and x=2 are both definitely assigned as
If a try statement does have a finally block, then these rules also
apply:
V is definitely assigned after the try statement iff at least one of the following is true:
V is definitely assigned after the try block and V is definitely assigned after every catch block in the try statement.
V is definitely assigned after the finally block.
V is definitely unassigned after a try statement iff V is definitely unassigned after the finally block.
The first error is a result of, well, unreachable code. Once you throw the exception, the method is halted, and the next line can never be executed. You can fix the second error by simply removing the final modifier from x. But I must ask, why are you writing a program whose only purpose is to throw a RuntimeException?
The java compiler can't look at things the same way we do as humans. It doesn't see cause and effect, only what is in error. And in this case it may be a good thing, because even if you fix one of the errors, the other will persist.
It's probably a language definition issue. One area of the spec prohibits reassignment if it might have already been assigned. A different area discusses unreachable code.
The combination of the two is probably never really addressed.
Could you perhaps supply something that is a bit more representative of what you are really trying to accomplish?
Looks like you are learning Java. The first error is because the compiler can see that execution of a block cannot continue after you throw an exception: control will jump to wherever the exception is caught. Other posters have explained the second error.
I've seen other cases that are less straightforward, for example something like:
final int x;
boolean b = ...;
if(b) {
x = 1;
}
...
if(!b) {
x = 2;
}
The easiest solution is to assign to a temporary non-final variable, then copy it to the final variable:
final int x;
int _x = 0;
boolean b = ...;
if(b) {
_x = 1;
}
...
if(!b) {
_x = 2;
}
x = _x;

final variable case in switch statement

final int a = 1;
final int b;
b = 2;
final int x = 0;
switch (x) {
case a:break; // ok
case b:break; // compiler error: Constant expression required
}
/* COMPILER RESULT:
constant expression required
case b:break;
^
1 error
*/
Why am I getting this sort of error? If I would have done final int b = 2, everything works.
The case in the switch statements should be constants at compile time. The command
final int b=2
assigns the value of 2 to b, right at the compile time. But the following command assigns the value of 2 to b at Runtime.
final int b;
b = 2;
Thus, the compiler complains, when it can't find a constant in one of the cases of the switch statement.
b may not have been initialized and it is possible to be assigned multiple values. In your example it is obviously initialized, but probably the compiler doesn't get to know that (and it can't). Imagine:
final int b;
if (something) {
b = 1;
} else {
b = 2;
}
The compiler needs a constant in the switch, but the value of b depends on some external variable.
The final variable without value assigned to it is called a blank variable. A blank final can only be assigned once and must be unassigned when an assignment occurs or once in the program.
In order to do this, a Java compiler runs a flow analysis to ensure that, for every assignment to a blank final variable, the variable is definitely unassigned before the assignment; otherwise a compile-time error occurs
That is why when the compiler compiles the switch construct it is throwing constant expression required because the value of b is unknown to the compiler.

Categories

Resources