Java Object Assignment
Asked Answered
T

8

24

I am new to Java and I have some questions in mind regarding object assignment. For instance,

Test t1 = new Test();
Test t2 = t1;
t1.i=1;

Assuming variable i is defined inside Test class, am I right to assume both t1 and t2 point to the same object where the modification t1.i=1 affects both t1 and t2? Actually I tested it out and seems like I was right. However when I try the same thing on String, the modification happens only on one side where the other side is unaffected. What is the reason behind this?

Edit: The case I tried with String.

String s1 = "0";
String s2 = s1;          
s1 = "1";
System.out.println(s1);
System.out.println(s2);

I realise my mistake by testing the cases on String since it is immutable. The situation where I thought s1="1" modify the string is in fact returning the reference of "1" to the s1. Nevertheless, my question remains. Does Test t2 = t1; cause both t2 and t1 point to the same object or each now have their own objects? Does this situation applies on all objects on Java?

Tutu answered 13/6, 2012 at 9:15 Comment(2)
What do you mean under 'try same thing on String'? There are no methods in String object to modify the string itself. Please read documentation carefully.Pilsen
If you post the code of the test you're doing on String, we can be more specific on what you're doing wrongFetching
M
20

You are right, but Strings are a special case; they are immutable and act like primitives in this case.

@newacct

I quote http://docs.oracle.com/javase/tutorial/java/data/strings.html :

Note: The String class is immutable, so that once it is created a String object cannot be changed. The String class has a number of methods, some of which will be discussed below, that appear to modify strings. Since strings are immutable, what these methods really do is create and return a new string that contains the result of the operation.

This is what makes strings a special case. If you don't know this, you might expect the methods discussed in the quote not to return new strings, wich would lead to unexpected results.

@user1238193

Considering your following question: "Does Test t2 = t1; cause both t2 and t1 point to the same object or each now have their own objects? Does this situation applies on all objects on Java?"

t1 and t2 will point to the same object. This is true for any java object (immutable objects included)

Mientao answered 13/6, 2012 at 9:17 Comment(5)
There are no "special cases". Assignment to a reference of any type changes the object it points to, without affecting the object it used to point to.Febrific
Strings are a special case; they are objects, but they are immutable, meaning if you try to change them by for example String.replace you'll get a new object instead of the same object mutated.Mientao
No, String simply happens to not have any method that changes it. "try to change them" does not make sense; you cannot "try" to do something that doesn't exist. String.replace gives you a new object -- what's your point? That is what its documentation says it will do. Integer and many other classes are immutable. You can trivially write a class that is immutable, by making fields private and providing no methods to change its fields. And in any case, mutability is irrelevant to the question, which originally was about changing a field on Test, but there are no public fields on StringFebrific
and then what do you do with the String pool, all classes have something like that ?Mientao
the String interning pool is completely irrelevant to this question or mutability. Any class may or may not have an interning pool like StringFebrific
R
8

You are right with your first assumption. With the following line of code:

Test t1 = new Test();

you create a new Test object, and in the same time you create a Test reference named t1 to refer to it.

At the second line of the code you posted:

Test t2 = t1;

You are actually creating another Test reference, and you assign it to refer to the same object that t1 refers to.

So t1.i = 1; will affect t2.i for it is the same object after all.

As for the Strings, Strings are immutable and can not be modified after instantiated.

Regarding your edit:

String s1 = "0";
String s2 = s1;          
s1 = "1";
System.out.println(s1);
System.out.println(s2);

They will print different results, because when you actually say

s1 = "1";

you are actually binding s1 to another String object, but s2 will still be refering to the object with value "0".

Rice answered 13/6, 2012 at 9:22 Comment(0)
F
5

You are doing completely different things in the two cases. In the first case, with t1.i = 1;, you are modifying the object pointed to by t1. In the second case, with t1 = "1";, you are changing the reference to point to another object (similar to when you did t2 = t1;.

If you do the same thing to Test that you did in the second case, you would get the same result (assuming Test has a constructor that takes an integer):

Test t1 = new Test(5);
Test t2 = t1;          
t2 = new Test(1); // Here we are assigning to the variable, just like your 2nd example
System.out.println(t1);
System.out.println(t2);

People mention that String is immutable. But that is irrelevant and there is no concept of "mutability" in the language and there is no difference between how "mutable" and "immutable" classes work. We informally say a class is "immutable" if it happens to not have any fields you can set or any methods that can change its internal content. Such is the case with String. But a mutable class would work the exact same way if you simply do not do anything to mutate it.

Febrific answered 13/6, 2012 at 18:4 Comment(1)
Before downvoting and commenting on other answers, please kindly bother to see the question edit history. That'll give you a hint as to why many answers,saying the same thing, were upvoted.Rossman
G
3

You are absolutely right, as both t1 and t2 refering to same object, any chane in the object state will affect to both.

String is an immutable object. So it cannot be modified at all. see this for more info on immutable object in java.

Gonsalve answered 13/6, 2012 at 9:17 Comment(1)
That doesn't explain the problem. The same thing is true of Test: Test s1 = new Test(2); Test s2 = s1; s1 = new Test(1);Febrific
R
2

String objects are immutable.


EDIT

Does Test t2 = t1; cause both t2 and t1 point to the same object or each now have their own objects?

Yes. Although t2 is a new reference, but it will point to the same object, because you told it to do so. Create a new reference t2 of type Test and let it point to the same object which t1 is pointing at.

But, when you do this with Strings and then do something like s1 = "1" ; you are making s1 point to another String object. You can think of it in terms s1 = new String(1);.

Rossman answered 13/6, 2012 at 9:18 Comment(3)
That doesn't explain the problem. The same thing is true of Test: Test s1 = new Test(2); Test s2 = s1; s1 = new Test(1);Febrific
@Febrific The OP edited the post later on. Initial post was answerable with these few words only. I'll edit my post now. Thanks for pointing it out though.Rossman
Even before the edit, "String is immutable" is not the correct answer. He said "when I tried the same thing on String"; the answer should be "What you said is impossible. It is impossible to do the same thing to String"Febrific
F
1

String are object like any other. So any variable you assign them refer to the very same instance of the object, like you are doing with your test object.

But keep in mind that String have no field you can set like you do on Test, so you basically cannot do the same test, so there is no way to port your code from Test object to String object.

You get opposite behaviour using primitive types, such long,int etc. They are assigned to variables "by value", so if you do

int t1 = 12;
int t2 = t1;
t1=15;

t2 still has value 12

Fetching answered 13/6, 2012 at 9:20 Comment(0)
B
0

Use StringBuilder as an example would be a litter bit clearer. Following example shows the object assignment just using the reference instead of the value.

{ StringBuilder str = new StringBuilder();

    str.append("GFG");

    StringBuilder str1 = str;

    str.append("tail");
    // output: str1 = GFGtail str = GFGtail
    System.out.println("str1 = " + str1.toString() + " str = " + str.toString());  

}

Brominate answered 7/5, 2020 at 2:46 Comment(0)
H
0

Because java uses the concept of string literal. Suppose there are 5 reference variables, all refers to one object "0".If one reference variable changes the value of the object, it will be affected to all the reference variables. That is why string objects are immutable in java.

Homophonous answered 20/10, 2020 at 6:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.