帮助java中的静态变量

时间:2010-06-29 20:06:29

标签: java static constructor new-operator

我有一个班级,

class MyClass {
    private int val;
    public static final MyClass myObject = new MyClass(1);
    MyClass(int a){
        val = a;
    }
    public int getVal(){
        return val;
    }
    public MyClass func1(){
        MyClass temp = myObject;
        temp.val = 2;
        return temp;
    }
    public static void main(String [] args){
        MyClass x = new MyClass(4);
        System.out.println(myObject.getVal());
        x.func1();
        System.out.println(myObject.getVal());
    }
}

打印:

 1
 2

我期待它打印出来:

 1 
 1

我似乎存在一个根本性的误解。我希望无法更改myObjectfinal static的值,当我执行MyClass temp = myObject时,我会创建一个名为temp的{​​{1}}类型的新对象,将MyClass的值分配给此新创建的对象。如果我错了,请纠正我。似乎没有创建新对象,myObject只是指向原始temp

编辑:谢谢你的回答!我现在明白myObject运算符永远不会复制对象,它只是复制引用。我需要的是复制=并将其存储在myObject中。实现这一目标的最佳方法是什么?

EDIT2:Java的另一个奇怪的行为或特征?

我稍微修改了代码

temp

输出

class MyClass {
    private Integer val;
    public static final MyClass myObject = new MyClass(1);
    MyClass(int a){
        val = a;
    }
    public int getVal(){
        return val;
    }
    public MyClass func1(){
        MyClass temp = new MyClass(33);
        temp.val = myObject.val;
        temp.val = 2;
        return temp;
    }
    public static void main(String [] args){
        MyClass x = new MyClass(4);
        System.out.println(myObject.getVal());
        MyClass y = x.func1();
        System.out.println(x.getVal());
        System.out.println(y.getVal());
        System.out.println(myObject.getVal());
    }
}

因此,当我使用 1 4 2 1 创建temp然后设置new MyClass(33)时,它实际上会复制val。换句话说,temp.val = 2并未指向temp.val。为什么会这样?

7 个答案:

答案 0 :(得分:7)

MyClass temp = myObject;

那不是创建一个新实例,它只是分配引用,以便temp指向与myObject相同的实例。

所以你的陈述:

  

我创建了一个名为temp of的新对象   输入MyClass

不正确,因为您没有在此处创建新对象,只需指定对象引用。

修改 如果您的目标是制作myObject的副本并从func1()返回,那么您可以这样做(通过复制我假设您的意思是复制val值,如果您想使用不同的val的值,然后您可以相应地调整此代码):

public MyClass func1(){
    MyClass temp = new MyClass(myObject.getVal());
    return temp;
}

答案 1 :(得分:5)

该字段为final,表示您无法重新分配该字段。但是,myObject var不是不可变的。当您在func1()上致电myObject时,您正在将myObject.val更改为2.

答案 2 :(得分:2)

您正在获取对MyClass对象的实例的引用并修改其中一个成员。该引用不是一成不变的;只有名为myObj的字段是不可变的。

答案 3 :(得分:1)

我认为你有点回答了你自己的问题。你说的是没有真正由行MyClass temp = myObject;创建的新对象temp是正确的,temp只是对myClass的静态实例的对象引用。

您可以通过修改代码来检查这一点。

public MyClass func1(){
    MyClass temp = myObject;
    System.out.println(myObject == temp);//print true
    temp.val = 2;
    return temp;
}

答案 4 :(得分:1)

在Java中,=运算符分配引用,而不是C ++中的对象。

最后一个字段只能分配一次。这并不意味着无法修改通过最终字段可到达的对象。

换句话说:与C ++的const不同,final只保护引用,而不是对象。

答案 5 :(得分:1)

阅读发布的答案后:

如果您希望临时引用变量保存引用。对于一个不可变对象,你可以使你的类不可变。

您可以在此处找到有关如何执行此操作的更多信息:

http://www.javapractices.com/topic/TopicAction.do?Id=29

http://java.sun.com/docs/books/tutorial/essential/concurrency/imstrat.html

答案 6 :(得分:0)

修饰符final的定义表明无法更改对象引用。 在第一个代码段

public static final MyClass myObject = new MyClass(1);

myObject是一个指向val = 1的对象的最终引用。 但是,这并不意味着不能更改对象的内容。 函数func1()获取值为1的对象的引用,并将其val更改为2。 因此它是完全合法的。

对于第二个片段

public MyClass func1(){
    MyClass temp = new MyClass(33);
    temp.val = myObject.val;
    temp.val = 2;
    return temp;
}
public static void main(String [] args){
    MyClass x = new MyClass(4);              //line A
    System.out.println(myObject.getVal());  //returns 1
    MyClass y = x.func1();                  //line B
    System.out.println(x.getVal());         //line C
    System.out.println(y.getVal());         //line D
    System.out.println(myObject.getVal());
}

在A行创建了一个带有val 4的obj 在第B行调用func1,总结创建一个val = 33的新对象,然后将其更改为val = 1然后val = 2。 在C行,我们从在A行创建的obj得到输出4 在D行,我们从使用B行的变化中得到输出2 在E行,我们从静态最终对象得到输出1,该对象没有改变。