Behaviour of local and class variables in java
Asked Answered
C

4

6

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.

Cosh answered 20/1, 2018 at 12:0 Comment(3)
y is not a static field. It's an instance field. So each Test instance has its own y. The method modifies y (i.e. this.y), not t.y. If you paint your car in black, your dad's car doesn't become black. Same here.Territoriality
This would have given you the same result in C++ too, with which you say you are familiar. Why are you surprised that Java behaves the same way?Feathered
I thought it may be problem with some variable scope in Java which I am unable to understand. But after knowing the actual reason behind this behaviour, yes the same will be in C++ too.Cosh
A
1

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.

Anemometer answered 20/1, 2018 at 12:7 Comment(0)
S
2

in method1 you have two objects t and this (current object) and the line

y = 44; // equivalent to this.y = 44

is setting the value of current object , so

this.y == 44; or y == 44;
t.y == 33;
Skittish answered 20/1, 2018 at 12:13 Comment(0)
P
2

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
}
Paraphrastic answered 20/1, 2018 at 12:56 Comment(0)
A
1

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.

Anemometer answered 20/1, 2018 at 12:7 Comment(0)
N
0

the point that you should understand is that y = 44 or this.y = 44 does not modify the t.y, if you want to modify the value of t.y you can do this: t.y = 44;

Neuritis answered 20/1, 2018 at 12:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.