java中的局部变量和类变量的行为

时间:2018-01-20 12:00:39

标签: java static class-level

我是Java编程语言的新手。
我熟悉C和C ++,但无法理解下面程序的行为。

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);
    }
}

正确输出:

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

预期输出:

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

即使将行从y = 44;更改为this.y = 44;也不会给出预期的输出。

4 个答案:

答案 0 :(得分:2)

静态和非静态变量的基本区别

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

对于学生non-static的每个对象,属性id和name将以其初始值(0& null)加载到内存中,每个对象的id和name可以不同。但是,在加载类执行时,collegeName只会被加载一次。因此,Student的每个对象都具有相同的大学名称。这就是static的含义。

访问静态和非静态变量

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;
    }
}

可以使用名称或类名帮助直接访问静态变量。当存在静态全局变量和局部变量时,静态变量应与类名

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

此处output将具有价值" foo "。局部变量总是具有更高的优先级,即全局静态变量以及String output = s1;将为null输出值的原因。

在静态块non-static内部必须使用引用变量访问变量(我们必须创建一个对象)。主要方法是静态的,这就是为什么我们必须创建Student的对象来访问idname的值,否则会产生编译时错误。

关于非静态块的盲目规则

每个非静态块将使用默认的this关键字表示当使用类级别(静态和非静态)变量时调用块的当前引用。示例java代码

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();
     }
}

当编译相同的代码以获取类文件

时会发生这种情况
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();
     }
}

此处this表示main方法中的引用变量student 表示调用块的引用变量。

回到这个问题,main方法创建了一个Test对象,并在其引用method1()上调用。因此,在method1 内,此只是在main方法中创建的引用变量t,而t是方法的本地引用变量。现在让我们以类文件格式重新编写代码

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
}

答案 1 :(得分:1)

问题是你没有提到创建的实际对象。您正在从具有新变量的其他实例中获取变量。

        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);

如果你仔细看第一行Test t = new Test();

你没有在y分配给44的特定实例上调用method1。因此你看到了顶级值。

如果重命名实例,将会更加清楚。而不是t总是。

这就是混淆的原因,而且你在里面调用method1()可能会导致你无休止的循环。

答案 2 :(得分:1)

method1 {p>你有两个对象tthis(当前对象)和行

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

正在设置当前对象的值,所以

this.y == 44; or y == 44;
t.y == 33;

答案 3 :(得分:0)

你应该理解的一点是,y = 44或this.y = 44不会修改t.y,如果你想修改t.y的值,你可以这样做: t.y = 44;