javacall-by-value

Is there a way to guarantee that a real referenced object has no side effect for a caller function?


I'm a student who recently learns JAVA.
I approaches this language based on my C++ experience.

So It took me almost four days to understand the gap between c++ and java in terms of the call-by-value or reference.

Java is call-by-value because a caller function passes a reference type variable itself to a callee.

When I understood the above sentence, a question comes to my mind suddenly.
My question is that...

I've learned that one of the call-by-value's advantages is no side effect.

In JAVA, It is guaranteed that a reference type variable itself has no side effect.
But a real object referenced by the reference variable may has side effect
after returns to a caller function.

So is there a way to guarantee that referenced object in heap memory also has no side effect for a caller function?

(And if I misunderstood the things around JAVA mechanism, please tell me)

==============================
Add a example

class Person{
    String  name;
    int     age;
    Person(String name, int age){
        this.name = name;
        this.age =age;
    }

}


public static void foo(){
    Person p = new Person("haha", 17);

    System.out.println(p.name); // haba

    boo(p);


    System.out.println(p.name); // hoho, but foo() wants original value "haha"

}

public static void boo(Person p){
    p.name = "hoho";

}

I want boo() function not to modify the member variable(p.name in here) of the p instance.


Solution

  • Below is a small example of how you can pass copies of objects, ensuring that the original object is not modified.

    When I use the copy constructor, the internal state of the original object is preserved, but when I simply state TestRef otherRef = testRef; only the reference is copied such that if the new object is modified, so is the original.

    Note that in this case I do copy the String reference since strings are immutable classes in java.

    public class Main {
    
        public static class TestRef {
            public String a;
            public int b;
    
            //Copy constructor
            public TestRef(TestRef other) {
                this(other.a, other.b);
            }
    
            public TestRef(String a, int b) {
                this.a = a;
                this.b = b;
            }
    
        }
    
        public static void main(String[] args) throws IOException, TransformerException {
    
            TestRef testRef = new TestRef("TestRef", 1);
            //Using copyConstructor to make deep copy of object
            System.out.println(testRef.a);
            TestRef deepCopy = new TestRef(testRef);
            modifyClass(deepCopy);
            System.out.println(testRef.a);
            //Shallow copy
            TestRef otherRef = testRef;
            modifyClass(otherRef);
            System.out.println(testRef.a);      
        }
    
        public static void modifyClass(TestRef testRef) {
            testRef.a = "newString";
            testRef.b++;
        }
    }
    

    OUTPUT:

    TestRef
    TestRef
    newString