2010-06-29 92 views
3

我有一个类的静态变量,帮助在Java

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 

似乎有成为根本的误解。我期待myObject是一个final static值不能改变,当我做MyClass temp = myObject时,我创建了一个新的对象temp类型MyClass,并将myObject的值分配给这个新创建的对象。如果我错了,请纠正我。看来,没有新的对象创建和temp只是指向原来myObject

编辑:感谢您的答案!我现在明白=操作符不会复制对象,它只是复制引用。我需要的是复制myObject并将其存储在temp中。什么是实现这一目标的最佳方式?编辑2:另一个奇怪的行为或Java的功能?

我修改了代码略微

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 

因此,当我使用new MyClass(33)创建temp然后设置temp.val = 2,它实际上使val的副本。换句话说,temp.val不指向myObject.val。这是为什么?

+0

我认为你正在尝试实现Singleton模式http://en.wikipedia.org/wiki/Singleton_pattern#Java 顺便说一句,你的问题已经答复在下面的多个答案。 – 2010-06-29 20:27:18

回答

7
MyClass temp = myObject; 

那不是创建一个新的实例,它只是分配,使温度指向同一个实例作为myObject的参考。

所以,你的发言:

我创建了一个名为 MyClass类型的临时

是不正确的新对象,你是不是在这里创建一个新的对象,只是分配一个对象引用。

编辑 如果你的目标是使myObject的副本,并从func1()返回它,那么你可以做到这一点(通过复制我假定你的意思复制val价值为好,如果你想使用一个不同的值为val那么你可以相应地调整此代码):

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

该字段为final,这意味着您不能重新分配字段。然而,你的myObject var不是不可变的。当您在myObjectfunc1(),要更改myObject.val到2

1

我觉得你有点回答你自己的问题。你说的没有真正的新对象MyClass temp = myObject;创建的新对象temp只是对myClass静态实例的对象引用。

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

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

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

1

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

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

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

+0

类型取决于你在C++(或C)中放置'const'的位置。 – 2010-06-29 23:19:49

0

的修改最终状态的定义,对象引用不能被改变。 在第一代码段

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线与OBJ VAL 4被创建。
在行B调用func1,总结创建一个val = 33的新对象,然后将其更改为val = 1,然后val = 2。
在C行,我们从A行创建的obj获得输出4。
在行D,我们从使用行B做出的更改中获得输出2。
在E行,我们从没有改变的静态最终对象中得到输出1。