0

Yes still learning the basics in Java! So the text I am referring to says - reference types (all except the primitives) are copied by reference. Now, I am also told Strings are reference types - which is why -

String str = "test";
String another_str = "test";

if ( str != another_str )
{
  System.out.println("Two strings are different"); // this is printed
}

If that is the case, why does this happen -

package prj_explore_infa_sdk;

public class parent_class {
  public String test;
  public parent_class (String str){
      test = str;
      test = "overriden";
  }
  public parent_class (){
      test = "overriden";
  }
}

package prj_explore_infa_sdk;

public class child_class extends parent_class{
    public static void main(String[] args){
        child_class cls = new child_class();
        if ( cls instanceof parent_class)
            System.out.println("Subclass is an instanceof parent class");
        String start = "nice";
        parent_class pclass = new parent_class(start);
        start = "changed";
        System.out.println("Start : " + start + ", pclass.test : " + pclass.test);
    }

}

This prints -

Subclass is an instanceof parent class
Start : changed, pclass.test : overriden

Why isnt this changing the member test of the pclass object, if the String reference was copied?

Bi Act
  • 334
  • 2
  • 3
  • 14
  • 1
    What output were you expecting and why? – Hovercraft Full Of Eels Aug 21 '14 at 03:21
  • Possible duplicate of http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value – Atul Aug 21 '14 at 03:23
  • Subclass is an instanceof parent class Start : changed, pclass.test : changed ? Since the start String reference was copied to the member test of the object pclass? – Bi Act Aug 21 '14 at 03:23
  • do you expect `System.out.println("Start : " + start + ", pclass.test : " + pclass.test);` this line to print `Start : changed, pclass.test : nice`? – Saif Aug 21 '14 at 03:47
  • @Atul I do not think it is a duplicate, but more a problem that a java String is not mutable. – Serge Ballesta Aug 21 '14 at 06:28

5 Answers5

2

In Java, everything is passed by value.

For reference types, the value passed happens to be an object reference.

The problem you run into is that

start = "changed"

is assigning your method's start variable a new String object reference, while pclass still has the old String object reference.

Incidentally, String objects are immutable and can't be modified.

Powerlord
  • 87,612
  • 17
  • 125
  • 175
  • to normal object, that is passed by reference i think. even though address is a kind of data, therefore a value, the way to think about it should be passing a address in memory should be considered as passing a reference. – Jason Hu Aug 21 '14 at 03:25
  • @HuStmpHrrr Thinking of it as purely pass by reference is wrong though. There's a very important difference between passing by reference, and passing references by value. – resueman Aug 21 '14 at 03:27
  • @resueman for sure it's not pure. primitives is passed by value. but still, if java is not passed by reference, method is not able to change the attributes of a passed in object, which is actually not true. – Jason Hu Aug 21 '14 at 03:30
  • ah - I didnt pay attention - that makes sense - coming back from the construction, reassigning changes the reference of 'start' but not of 'test' – Bi Act Aug 21 '14 at 03:30
  • @HuStmpHrrr Implying that Java is pass by reference for objects is wrong. Java is **completely** pass by value, for both primitives and object references. – resueman Aug 21 '14 at 03:43
  • wait - if everything is passed by value, then you wouldnt be able to manipulate the objects passed to methods as arguments (and get the modified object back), right? – Bi Act Aug 21 '14 at 04:00
  • Also, like @Powerlord pointed out - since Strings are immutable, this was perhaps a bad example. What if "start" and pclass.test were instead a reference type like "foo"? Wouldnt creating pclass with "start" as a constructor argument, and then subsequently modifying "start" modify "pclass.test"? – Bi Act Aug 21 '14 at 04:18
  • @BiAct If you modify properties/call methods on `pclass`, then yes. If you assign it a new `foo` object, then no. The latter point would be "yes" in C# if you had a `ref` parameter, for example. Modifying the original after creating a copy is actually a common practice for `List`s / `Collection`s. Java 1.5 added some thread-safe collections to help deal with the side effects of modifying them in different threads (the new ones are in the `java.util.concurrent` package). – Powerlord Aug 21 '14 at 13:31
0

why should?

'start' is a reference and it references a new string object 'changed'. you are not understand reference in a right way. reference is pointer.

Jason Hu
  • 6,239
  • 1
  • 20
  • 41
0

In your code in parent_class first test is pointing to null. When you called

parent_class pclass = new parent_class(start); the control from this line went to:
public parent_class (String str){

in above line str is referring to the start's reference which has "nice" as string.
now when you attempt to do test = str;, test variable now referred to the str which has the reference of start so test variable should point to "nice" but again in next line test = "overriden"; you are assigning test variable to another "overriding" which changes test's reference from str to a new one. Hence you are getting pclass.test : overriden

jcool
  • 314
  • 1
  • 3
  • 11
0
String str = "test"; 
String another_str = "test";

String is a special. The literal of "test" is stored in a constant pool.

Whenever you use the literal "test", they will be referenced to that location.

That's why str==another_str is true;

Check the below output, and you may figure out this:

    String str = "test";
    String another_str = "test";
    //str and another_str points to the same one.

    String another_str2=new String(str);//Created a new String and points to taht 

    System.out.println(str==another_str);//true     
    System.out.println(str==another_str2);//false, though they have the same string value
JaskeyLam
  • 15,405
  • 21
  • 114
  • 149
0

It is because a String is an immutable object.

So when you create your parent object with start as creator argument, the test = str effectively causes test point to start.

But the next line does not cause start to be overwritten, but simply causes test to point to "overriden".

If you used an ArrayList (mutable object) and in constructor you add an element to the list, then the original list would be modified with the new element.

Hope I've understood your question ...

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252