Java - static initialization - java

I have written a piece of code :
public class Child{
int y ;
private static final int z = getZ();
static {
System.out.println("The value of z is "+z);
}
public int getX(){
System.out.println("get x");
return 10;
}
public int getY(){
Child ch = new Child();
System.out.println("get y");
ch.y = getX();
return y;
}
public static int getZ(){
System.out.println("get z");
return new Child().getY();
}
public Child(){
System.out.println("Child constructor");
}
public static void main(String...args){
Child ch = new Child();
System.out.println("the value of z in main is "+z);
}
}
And the output is :
get z
Child constructor
Child constructor
get y
get x
The value of z is 0
Child constructor
the value of z in main is 0
Can anyone please explain me why the value of z is 0 and not 10 ?
EDIT:- Thanks everyone , I got the answer to my first question . I still have a doubt , as far as I know the static blocks are executed after the class is loaded and before the first object of the class is instantiated . Well then the SOP("The value of z is "+z) should have been executed before SOP("Child constructor") ! Ain't it ?

Look at getY():
public int getY(){
Child ch = new Child();
System.out.println("get y");
ch.y = getX();
return y;
}
The first three lines are irrelevant - they don't change the value of y in this instance, which is what gets returned.
You're creating an awful lot of pointless objects in frankly spaghetti code, called while initializing the same class that you're constructing instances of. I suggest you try to keep your code a lot simpler than this. Static initializers should be avoided where possible to start with, let alone ones that go all round the houses to do no useful work.

because getY() sets ch.y to 10, but returns the value of this.y.

In GetY you return this.y which never gets set.

On getY() you returned the uninitialized y variable instead of the Child ch instance.

Its because inside getY() method you are constructing a new CHild object and you are assigning 10 to that instance of variable y and when you return y that will be the current instance variable y.
I hope it explains .

To your second point, static fields and static blocks are initialized / executed in textual order.
Eg:
public class StaticTest()
{
static
{
System.out.println("s1 in block 1 :" + s1);
}
private static String s1 = "s1";
static
{
System.out.println("s1 in block 2 : " + s1);
}
public static void main(String args[])
{
new StaticTest();
}
}
The output of this will be -
s1 in block 1 :
s1 in block 2 : s1

Related

Variable Hiding confusion?

So this is basically my code
abstract class B
{
int x = 3;
B()
{
x+=2;
System.out.print("-x" + x + "\n"); // print -x5
x++; // 5 then 6
}
abstract int calculate();
abstract int calculate(int i);
}
class A extends B
{
int x = 2;
A()
{
System.out.print("-x" + calculate(2)+"\n");
}
#Override
int calculate()
{
return x;
}
#Override
int calculate(int i)
{
return(calculate()+i);
}
}
public class Test2 extends A
{
Test2()
{
x+=3;
}
#Override
int calculate()
{
return x + 6;
}
public static void main(String[] args) {
Test2 sub = new Test2();
System.out.print("-x" + sub.calculate()+"\n");
}
}
My problem here is after digging up about variable hiding I learned that if a instance variable is of the same name in both parent class and child class then the childclass hides the instance variable of the parent class. Also I have the prior knowledge that variables cannot be overridden when child class inherits parent class.
So now coming to the problem, in the code when A extends to B, why does the print statement inside constructor A() gives a value -x10? shouldn't it be -x8?? I dont understand how the variable is being changed here. I am new to java so any kind of knowledge will be greatly appreciated. :)
Ok so I have done some debugging and found that the calculate(void) method in class A returns 8. But how is that possible shouldn't it return 6? Please help!
The reason it prints -x10 is because A::calculate(2) calls the Test2::calculate(), which uses A::x to do the calculation.
The sequence of calls that happens is the following:
Test2() {
A()
B() {
B::x = 3
B::x += 2
System.out.print("-x" + x + "\n"); // print -x5
B::x++ // B::x is now 6
}
A::x = 2
System.out.print("-x" + calculate(2)+"\n")
A::calculate(2) {
return(calculate()+2);
Test2::calculate() {
return A::x + 6; // A::x is 2 here, so returns 8
}
} // returns calculate()+2, so returns 10
}
A::x += 3
}
I hope this is just code to test things out, because you should never allow this to happen in real code. You should never allow a method of a subclass to be called from the constructor of a base class, because the subclass is not initialised at that time. The Java compiler does its best to prevent that, but sometimes it does not detect it.
It is returning 8 because:
The line you called System.out.print("-x" + sub.calculate()+"\n"); in class A calls
#Override
int calculate()
{
return x + 6;
}
in class A still, which is incrementing the instance variable int x = 2 in class A . this variable overwrote the one in class B
Hence 2+6 = 8

using a param of a resulting method in main method

If I have a method e.g.
public int addition(int x, int y)
{
int z = x + y
return z;
}
public int usez(int z)
{
// TODO
}
public static void main(String [ ] args)
{
classname d = new classname();
d.usez(z)...
}
z is not readable. So, is there a way to make the resulting z from the first method into the usez method when testing it in main =/
hopefully this makes some sense! in a real version e.g. if x,y = 1,2 then z = 3 I want the main method to recognise z to be 3.
z is a private local variable for the method addition. You can't and should not attempt to access it. However, it's value is returned by the function it's defined in (addition). Therefor, you can do the following:
classname d = new classname();
int zValue = d.addition(1,2);
d.usez(zValue);
Assuming that all methods including main() are in same class, You can make z as class member variable as
int z= 0;
and assign value to it in
public int addition(int x, int y)
{
z = x + y
return z;
}
and use in usez(z).
public static void main(String [ ] args)
{
classname d = new classname();
d.usez(z)...
}

Final non-static data member

If you are not allowed to initialize a final non-static data member twice, then how can I set x to something that I want in the following example?
class Temp6
{
final int x;
Temp6()
{
System.out.println(this.x);
this.x=10;
}
public static void main(String[]s)
{
Temp6 t1 = new Temp6();
System.out.println(t1.x);
}
}
Java by default gives x a value of 0, so how can I change it to 10?.
A variable marked final in Java can only be initialized once.
Simply declaring x with final int x; does not initialize it. Therefore, it is legal to assign to x in the Temp6 constructor. However, you would not be able to assign a different value to x after the constructor.
That is, the assignment to t1.x in the following:
public static void main(String[] s) {
Temp6 t1 = new Temp6();
t1.x = 11; // ERROR
}
is not legal.
Initialize final variables in the class constructor.
public class Blam
{
private final int qbert;
public Blam(int qbertValue)
{
qbert = qbertValue;
}
}
Reading this.x in your code should give an error, because final variables are not initialized upon declaration. t1.x should be 10 because x is definitely assigned at the end of the sole constructor.
You have to swap the two lines in the constructor for it to compile and it will be 10 there.
class Temp {
int x; // declaration and definition; defaulted to 0
final int y; // declaration, not initialized
Temp() {
System.out.println(x); // prints 0
x = 1;
System.out.println(x); // prints 1
x = 2; // last value, instance.x will give 2
System.out.println(y); // should be a compiler error: The blank final field y may not have been initialized
y = 3; // definite assignment, last and only value, instance.y will be 3 whereever used
System.out.println(y); // prints 3
y = 4; // compile error: The final field y may already have been assigned
}
}
I never thought about this before, interesting point here.
Final field variables behave like local variables in methods, they must be explicitly assigned before usage (definite assignment is hard to formalize, see JLS reference, but it's quite logical).
If you want to give a value to x from outside, you could do it like this:
public class Temp {
private final int x;
public Temp(int x) {
this.x = x;
}
public int getX() { return this.x; }
public static void main(String[] args) {
Temp temp = new Temp(10);
System.out.println(temp.getX()); // 10
}
}
final variable are java constants. They should be initialized before class loads.
final int x=10;
If your final variable is static then it's not like you have to give the value at the declaration itself, you can have something like -
class Demo {
static final int x;
static {
x = 10;
}
}
static block gets executed only once, at the time of class loading

Java considering List argument as reference

I was doing some RnD I came across this this difference
my java code is as below
public class Main {
public static void main(String[] args) {
Integer x = 10;
increment(x);
System.out.println("print x" + x);
List<String> strList = new ArrayList<String>();
strList.add("one");
strList.add("two");
strList.add("three");
strList.add("four");
strList.add("five");
strList.add("six");
System.out.println("Before removing");
for (String string : strList) {
System.out.println("item " + string);
}
removeSomeItem(strList);
System.out.println("After removing");
for (String string : strList) {
System.out.println("item " + string);
}
}
private static void removeSomeItem(List<String> strList) {
strList.remove(0);
strList.remove(4);
}
private static void increment(Integer x) {
x++;
}
}
I got out for the above code as below
print x10
Before removing
item one
item two
item three
item four
item five
item six
After removing
item two
item three
item four
item five
my question is when I had sent Integer to function it behaved like value same way when I had sent List<String> its behaving like reference why is this difference ?
can any one explain
The main difference is that the Integer class is immutable, hence why you do not see the change in your main method.
x++; // this will simply return a new Integer
To see the difference, try this from your main method:
x = increment(x);
and in the increment method, change it to this:
return x++;
However, with your list example, you are simply passing a copy of the reference to the list. As long as that reference is not set to a new object (which it isn't), it is able to update the original list you passed.
This is exactly what happened
private static Integer b;
public static void main(String[] args) {
Integer x0 = 10;
b = x0;
increment(x0);
}
private static void increment(Integer x1) {
//x1 == b is true
x1++; //implies x1 = x1 + 1;
//x1 == b is now false
//at the end of the day, you've done nothing to x0 or b
}
EDIT: This code will fail because apparently, the JVM is caching Integer values between -128 and 127, see here, set x0 = 150 and test.
public class Main {
static Integer b;
public static void main(String[] args) {
Integer x = 150;
b = x;
increment(x);
}
private static void increment(Integer x) {
System.out.println(x == b); //true
x++;
System.out.println(x == b); //false
b++;
System.out.println(x == b); //false
}
}
Well in case of,
removeSomeItem(strList);
you are passing the address of original ArrayList to the method so when it remove some value using that reference the original ArrayList change too (actually they are single object with two access point , I mean the reference ).
But in case of Integer you also pass the reference and the increment(Integer x) method receive the original reference. But as Integer immutable when I do something like,
x++;
In the background its work like
x=new Integer(x+1);
That’s why the original Integer remain unchanged when the ArrayList change.

Object Creation in java and finalize

class FDemo {
int x;
FDemo(int i) {
x = i;
}
protected void finalize() {
System.out.println("Finalizing " + x);
}
void generator(int i) {
FDemo o = new FDemo(i);
System.out.println("Creat obj No: " + x); // this line
}
}
class Finalize {
public static void main(String args[]) {
int count;
FDemo ob = new FDemo(0);
for(count=1; count < 100000; count++)
ob.generator(count);
}
}
}
In the line i have commented, the value of x always shows 0(value of x in object ob), why isnt showing the value of object o?? i know if i use o.x i ll be getting the value of x in object o. But still in this code why does it show the value of abject ob rather than object o??
If you want to reference the x in the FDemo you've just created, you should add a getX() function and call that instead of x, like David Wallace said. (I prefer using getters instead of .variable).
Add this to your class:
public int getX(){
return x;
}
And change your problematic line to this:
System.out.println("Creat obj No: " + o.getX());
That should fix it. As a side note, it's considered good practice to explicitly declare whether your variables and methods are private, public or protected.

Categories

Resources