I am a little bit confused about the following piece of code:
public class Test{
int x = giveH();
int h = 29;
public int giveH(){
return h;
}
public static void main(String args[])
{
Test t = new Test();
System.out.print(t.x + " ");
System.out.print(t.h);
}
}
The output here is 0 29, but I thought that this has to be a compiler error, because the variable h should have not been initialized when it comes to the method giveH(). So, does the compilation go through the lines from top to bottom? Why is this working? Why is the value of x 0 and not 29?
The default value of int is 0 (see here). Because you initialize x before h, giveH will return the default value for a int (eg 0).
If you switch the order like this
int h = 29;
int x = giveH();
the output will be
29 29
Compilation in Java doesn't need the method to be declared before it is used. The Java tutorial goes into a bit more detail on initialization.
Here's a way to think about it: the compiler will make a note to look for a method called giveH somewhere in scope, and it will only error if it leaves the scope and doesn't find it. Once it gets to the giveH declaration then the note is resolved and everyone is happy.
Also, the variable initialization for instance variables in Java is moved to the beginning of the constructor. You can think of the lines above being split into two parts, with the declaration for x and h above, and the assignment inside the constructor.
The order of declaration does matter in this case. When the variable x is initialized, h has the default value of 0, so giveH() will return that default value. After that, the variable h is given the value 29.
You can also look at the Java Language Specification sections on Field Initialization and Forward References During Field Initialization.
#Maloubobola has provided the correct answer, but since you don't seem to fully understand yet, let me try to elaborate.
When Test is created, it runs the variable initialization (x = giveH(), h= 29) once. Your misunderstanding may be that variable x is always determined by giveH(), whereas it only determines it's value when x is initialized.
That's why the order of the statements is crucial here; x is initialized before h, and therefore h is 0 when giveH() is called at x's initialization.
It's bad practice to use a method in the field initializer. You can fix this by making h final. Then it will be initialized when the class is loaded.
import java.util.ArrayList;
public class Test {
int x = giveH();
final int h=29;
final public int giveH(){
return h;
}
public static void main(String args[]) {
Test t = new Test();
System.out.print(t.x + " ");
System.out.print(t.h);
}
}
If we do not initialize the value for non static variables like x in this program JVM will provide default value zero for class level non static variables.
Once declared, all the array elements store their default values.
Elements in an array that store objects default to null.
Elements of an array that store primitive data types store:
0 for integer types (byte, short, int,long);
0.0 for decimal types (float and double);
false for boolean;
\u0000 for char data.
Actauls values will come only when we give initialize them
Related
Is this code safe in Java?
public class HelloWorld {
public static void main (String args[]) {
HelloWorld h = new HelloWorld();
int y = h.getNumber(5);
int z = h.getNumber (6);
if (y == 10)
System.out.println("true");
}
public int getNumber(int x) {
int number = 5;
number = number + x;
return number;
}
}
My co-worker says that int number will be placed on the stack and when getNumber returns it will be popped off and could potentially be overwritten.
Is the same code potentially unsafe in C?
The HelloWorld class has no fields, and is therefore immutable. You can call your getNumber(x) function as many times as you'd like, from any thread, using the same object, and it will always give the same result for the same argument.
Maybe your co-worker is recalling horror stories in C where you can have something like static int number, which "belongs" to the method and which would get overwritten. Or maybe she's thinking about "return by reference"; even if it were, you'd be referencing a brand-new object every time because number is newly instantiated for every method call.
Your coworker is correct, sort of, but they apparently misunderstand what is going on.
public int getNumber(int x) {
int number = 5;
number = number + x;
return number;
}
Yes the value of 5 + 5 or 5 + 6 will be placed on the stack, but there is no danger of them being overwritten, they will properly be placed into y or z.
I suspect the confusion is from C (this type code works fine in C as well), but for pointers instead of primitives. Returning a result of malloc from a function in C can be "challenging" if you don't do it right.
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.
So I'm trying to declare an integer variable inside an if/else statement, and print it out, outside of it. Something like this:
int x;
int a = 1;
if (a == 1)
{
int x = 5;
}
System.out.println(x);
This is just an example of what I'm trying to do, as I don't have the actual code with me, and i don't want to redo it all over. Although it shouldn't matter really, as the example is exactly what i need, only with different variable values and names (but it's still an integer). At first i just declared and initialised the variable inside the if/else statement, but then I was told I need to declare it outside the statement... So I did that, then initialised it within the statement, and then proceeded to call on it later on. However I'm still getting an error, either it says the variable hasn't been initialised, or if I assign a value to it (x) then update it inside the statement, the error i get is that it has already been declared. Any help would be appreciated, thanks.
Yes. Local variables needs to be initialize before they use. Where as instance variables initialize to default values if you didn't initialize them before use.
If you are curious about the reason? click here to know
Coming back to your question again,
Because consider the below scenario
Follow comments.
int x; // declared with no value
int a = 0;
if (a == 1) // this is false
{
x = 5; // this never executed
}
System.out.println(x); // what you are expecting to print here ?
Hence you need to initialize with a value. For ex : initialize it with zero and change it later on based on a condition
int x=0;
int a = 1;
if (a == 1)
{
x = 5;
}
System.out.println(x);
Simply assign the int x = 0 before your if-statement, then instead of redeclaring x as an integer equal to 5, set x equal to 5 inside your if statement.
The point is that you declared x above. So remove int before x inside the if-statement. Then it works.
int x;
int a = 1;
if (a == 1) {
x = 5;
}
System.out.println(x);
Implicitly an integer is initiated with 0. If you want to be sure just write
int x = 0;
your code here
int x = -1;
int a = 1;
if (a == 1)
{ // here begins inner 'area' for declared variables
x = 5;
}// and here ends
System.out.println(x);
OK, my bad! I wanted him to wonder why and try some other ways of writting it and letting him get 'hit' by IDE errors.
So Mr. Unknown as far as you declare variable 'inside' if statement it is visible only across that statement! So basicly if You want to do something with variable inside if statement, and have results outside of it, You need to declare it outside the statement making it having wider range of accessibility! If You have any questions don't hesitate to ask ;)
P.S. Watch out for re-declaring variable with the same name like You tried to do here, it's nasty bug to find =)
Thank you all for the answers, I realized I made 2 minor mistakes that didnt allow it to work, I (in most attempts) didn't declare a value for x before the if statement, and I had 'int' in front of x inside the if statement, which caused the re-deceleration error. So yea, thank you for the quick answers :)
I am super new to programming and I'm studying for a test and don't understand the output of a piece of code. I was hoping you could help me understand why the 4 is being printed at the end?
I threw the code in the Java visualizer site and I understand everything except why the line...
System.out.println(myScope.z); would print the number 4?
Any help is greatly appreciated!
public class ScopeTest {
int z;
public static void main(String[] args){
ScopeTest myScope = new ScopeTest();
int z = 6;
System.out.println(z);
myScope.doStuff();
System.out.println(z);
System.out.println(myScope.z);
}
void doStuff() {
int z = 5;
doStuff2();
System.out.println(z);
}
void doStuff2() {
z=4;
}
}
ScopeTest myScope = new ScopeTest(); initializes myScope.z to 0 (default value)
myScope.doStuff(); sets myScope.z to 5 and calls doStuff2()
doStuff2() sets myScope.z to 4.
The final result being 4. Key point is that the local z variables declared in the main and doStuff() methods have no bearing whatsoever on the z member variable declared in ScopeTest.
Stepping through code one line at a time is a good exercise to figure out what it is doing. You should do this with paper and pencil as well as with a debugger. So let's step through your code one line at a time in the order of execution. After each line of code, I'll explain what it does.
ScopeTest myScope = new ScopeTest();
Create a local reference variable named myScope and initialize it to an object.
int z = 6;
Create a local int variable named z and initialize it to 6.
System.out.println(z);
Print the value of the local variable z.
myScope.doStuff();
Call doStuff() on the myScope object.
int z = 5;
Create a local variable z in doStuff() and initialize it to 5.
doStuff2();
Call doStuff2()
z=4;
Set the member field named z to the value 4. And then return control back to doStuff().
System.out.println(z);
Print out the value of the local variable z. And then return control back to main().
System.out.println(z);
Print out the value of the local variable z. (Remember we are back in main() now.
System.out.println(myScope.z);
Finally, print out the member field z. (Remember its value was set back in doStuff2(). This value is remembered because this z is a member variable.)
This is the Flow:
myScope.doStuff() --> 1. z=5 2. doStuff2() --> z=4
You are calling dostuff() in main() method, there you have initialized z=5 which is its local variable z and not class variable z. so then you are calling dostuff2() in which you are actually modifying class variable z=4. That is why it is printing z=4 in last syestem.out.println(z). Hope this will help you understanding output.
because In your code z declared in the first line, is instance member (this context).
so when ever doStuff2() is called this.z is set to 4.
//effectively
void doStuff2() {
this.z=4;
}
the variables int z declared inside the methods main and doStuff() are in local context.
and here, it only matters when the value of z in this context is set finally (which is inside doStuff2()).
Thus,
System.out.println(z); >> prints value of local variable z declared in main
System.out.println(myScope.z); >> prints the value of instance (of ScopeTest which is myscope here) member z
I'm studying up for the SCJP exam, upon doing some mock tests I came across this one :
It asks what is the output of the following :
class TestClass
{
int i = getInt();
int k = 20;
public int getInt() { return k+1; }
public static void main(String[] args)
{
TestClass t = new TestClass();
System.out.println(t.i+" "+t.k);
}
}
I thought it would be 21 20, since t.i would invoke getInt, which then increments k to make 21.
However, the answer is 1 20. I don't understand why it would be 1, can anyone shed some light on this?
The variables are initialized from top to bottom.
This is what happens:
Initially both i and k have the (default) value 0.
The value computed by getInt() (which at the time is 0 + 1) is assigned to i
20 is assigned to k
1 20 is printed.
Good reading:
The Java™ Tutorials: Initializing Fields
jvm will follows like this,
1.identification for non-static members from top to bottom
2.executing non-static variables and blocks from top to bottom
3.executing the constructor......
in the first step jvm will provide default values..on that time variables in readindirectly write only state..