views:

149

answers:

7

I have a class,

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

It prints:

 1
 2

I was expecting it to print:

 1 
 1

There seems to be a fundamental misunderstanding on my part. I was expecting that myObject being a final static value cannot be changed, and when I do MyClass temp = myObject, I create a new object called temp of type MyClass and assign the value of myObject to this newly created object. Please correct me if I am wrong. It seems that the there is no new object created and temp simply points to the original myObject

EDIT: Thanks for the answers! I now understand that the = operator never makes a copy of the object, it just copies the reference. What I need is to make a copy of myObject and store it in temp. What would be the best way to achieve this?

EDIT2: Another strange behavoir or a feature of Java?

I modified the code slightly

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

output is

 1
 4
 2
 1

Therefore, when I create temp using new MyClass(33) and then set temp.val = 2, it actually makes a copy of val. In other words, temp.val does not point to myObject.val. Why is this so?

+6  A: 

The field is final, which means that you cannot reassign the field. Your myObject var, however, is not immutable. When you call func1() on your myObject, you are changing myObject.val to 2.

akf
+7  A: 
MyClass temp = myObject;

That's not creating a new instance, it's just assigning the reference so that temp points to the same instance as myObject.

So your statement:

I create a new object called temp of type MyClass

is incorrect, as you aren't creating a new object here, just assigning an object reference.

EDIT If your goal is to make a copy of myObject and return it from func1(), then you could do this (by copy I assume you mean copying the val value as well, if you want to use a different value for val then you can adjust this code accordingly):

public MyClass func1(){
    MyClass temp = new MyClass(myObject.getVal());
    return temp;
}
dcp
+1  A: 

I think you have kinda answered your own question. You are correct in saying that there isn't really a new object created by the line MyClass temp = myObject; temp is only an object reference to your static instance of myClass.

You can check this by modifying the code as so.

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

You are obtaining a reference to an instance of the MyClass object and modifying one of its members. That reference is not immutable; only the field named myObj is immutable.

Eric Hauser
+1  A: 

In Java, the = operator assigns references, not objects like in C++.

A final field can only be assigned once. That does not mean that objects reachable through a final field can not be modified.

Put differently: Unlike C++'s const, final only protects the reference, not the object.

meriton
Kind of depends where you put the `const` in C++ (or C).
Tom Hawtin - tackline
+1  A: 

After reading the posted answers:

If you want the temp reference variable to hold a ref. to an immutable object you can make your class immutable.

You can find more information on how to do that here:

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

or

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

andreas
A: 

Definition of the modifier final states that the object reference cannot be changed. In the first code snippet

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

myObject is a final reference which is pointing to a object with val =1. However this does not imply that the contents of the object cannot be changed. the function func1() gets a reference on the object with value 1 and changes its val to 2. thereby it is perfectly legal.

For the second snippet

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

At line A obj with val 4 is created.
At line B func1 is called which in summary creates a new object with val=33 which is then changed to val=1 and then val=2.
At line C we get output 4 from the obj created at line A.
At line D we get output 2 from the changes we made in using line B.
At line E we get output 1 from the static final object which is not changed.

frictionlesspulley