Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Behaviour of local and class variables in java

Tags:

I am new in Java Programming language.
I am familiar with C and C++ but unable to understand the behaviour of the below program.

public class Test {
    static int x = 11;
    private int y = 33;
    public void method1(int x) {
        Test t = new Test();
        this.x = 22;
        y = 44;    
        System.out.println("Test.x: " + Test.x);
        System.out.println("t.x: " + t.x);
        System.out.println("t.y: " + t.y);
        System.out.println("y: " + y);
    }    
    public static void main(String args[]) {
        Test t = new Test();
        t.method1(5);
    }
}

Correct Output:

Test.x: 22
t.x: 22
t.y: 33
y: 44

Output expected:

Test.x: 22
t.x: 22
t.y: 44   // As variable y is modified inside the function.
y: 44

Even changing the line from y = 44; to this.y = 44; is not giving the expected output.

like image 731
Bhawan Avatar asked Jan 20 '18 12:01

Bhawan


2 Answers

Basic Difference between static and non-static variables

class Student {
    private int id;
    private String name;
    static String collegeName;
}

For every object of Students non-static attributes id and name will be loaded into memory with its initial values (0 & null), id and name can be different for each object. But collegeName will only be loaded once, that's when class is loaded for execution. So for every object of Student will have same college name. That's what is meant by static.

Accessing static and non-static variables

class Student {
    private int id;
    private String name;
    static String collegeName;
    public static void main(String[] args) {
        String s1 = Student.collgeName;
        String s2 = collgeName;
        Student student = new Student();
        String s3 = student.name;
        int id = student.id;
    }
}

Static variables can be accessed directly by using their name or using the help of class name. When there is a static global variable and a local variable, the static one should be used along with the class name

public static void main(String[] args) {
    String s1 = Student.collgeName;
    String collgeName = "foo";
    String output = collgeName;
}

Here output will be having value "foo". Local variable is always having higher priority that global static variable and that's why String output = s1; will give value for output as null.

Inside a static block non-static variables must be accessed with the help of reference variables (We have to create an object). Main method is static that's why we had to create object of Student to access the values of id and name, otherwise it will give compile time error.

Blind rule regarding non-static blocks

Every non-static blocks will be using a default this keyword representing current reference on which the block is invoked when a class level (static as well as non-static) variables are used. Sample java code

class Student {
     private int id;
     private String name;
     static String collegeName;
     void setData() {
         id = 1;
         name = "foo";
         collegeName = "FooCollege";
     }
     public static void main(String[] args) {
         Student student = new Student();
         student.setData();
     }
}

This is what happens when the same code is compiled to get the class file

class Student {
     private int id;
     private String name;
     static String collegeName;
     void setData() {
         this.id = 1;
         this.name = "foo";
         this.collegeName = "FooCollege"; // which will be again as Student.collegeName
     }
     public static void main(String[] args) {
         Student student = new Student();
         student.setData();
     }
}

Here this representing the reference variable student from main method. Represents the reference variable on which the block is invoked.

Coming to the question, main method creates a Test object and on its reference method1() is invoked. So inside method1 this is nothing but reference variable t created in main method and t is the local reference variable of the method. Now lets re-write the code in class file format

public void method1(int x) {
   Test t = new Test();
   this.x = 22;  //  or Test.x = 22;
   y = 44;  //  or this.y = 44;
   /* 
       Test object inside method1 and main method are in two different locations.
       When we write this.y = 44; the y inside the main method object will be changed and not the one created inside method1.
   */
   System.out.println("Test.x: " + Test.x);
   System.out.println("t.x: " + t.x);
   System.out.println("t.y: " + t.y); // means the y inside the object created inside method1
   System.out.println("y: " + y); // means the y inside the object created inside main method
}
like image 103
Arun Sudhakaran Avatar answered Oct 13 '22 01:10

Arun Sudhakaran


The problem is you are not referring to the actual object created. You are reffering the variable from other instance which have fresh variables.

        Test t = new Test();
        this.x = 22;
        y = 44;

        System.out.println("Test.x: " + Test.x);
        System.out.println("t.x: " + t.x);
        System.out.println("t.y: " + t.y);
        System.out.println("y: " + y);

If you look close at very first line Test t = new Test();

you are not calling method1 on that particular instance where y is assigning to 44. Hence you seeing the top level value.

It will be more clear if you rename your instances. Instead of t always.

That is the reason for the confusion and also, you call method1() inside that might lead to you a endless loop.

like image 25
Suresh Atta Avatar answered Oct 13 '22 01:10

Suresh Atta