0

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.

user7024
  • 311
  • 2
  • 10
  • Not sure I follow your question, but you can do what you are after by marking the parameter as `final`. More information [here](https://stackoverflow.com/questions/500508/why-should-i-use-the-keyword-final-on-a-method-parameter-in-java/10380512). – npinti Jan 17 '20 at 06:44
  • 4
    "is there a way to guarantee" - there is. If you want to make sure the object is not changed in a function, you can create a copy of that object and pass it instead. Another approach could be - making an object immutable or declaring an interface that does not allow any changes. – Pavel Smirnov Jan 17 '20 at 06:46
  • Can you show some code illustrating what you are asking? Objects and variables don't have side effects. Methods and functions do. I don't really understand what you're asking, really. – Sweeper Jan 17 '20 at 06:56
  • @Sweeper, sorry. I added a example – user7024 Jan 17 '20 at 07:06
  • @Pavel Smirnov thanks. "Copy and pass" way you've mentioned is what I want to know. That is simple but awesome way. – user7024 Jan 17 '20 at 07:10

2 Answers2

0

You can do this:

class Person{
    final String name;
    int age;
Person(String name, int age){
        this.name = name;
        this.age =age;
    }
}
Cleo
  • 136
  • 1
  • 10
  • A final object still can be modified but not re-assigned. In this case, name of type String is re-assigned. Is this is explanation – papaya Jan 17 '20 at 08:01
  • @Cleon your answer is also helpful, but what intended to do was that Person p can be modified anytime if it is in foo function but not in boo function. – user7024 Jan 17 '20 at 10:26
0

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
Jonaswg
  • 394
  • 2
  • 12
  • "copy and pass" mechanism (mentioned above) is implemented based on the copy constructor. I knew all the concepts but bringing them together is hard for me yet. – user7024 Jan 17 '20 at 10:38
  • I hope this answers your questions :) – Jonaswg Jan 17 '20 at 13:16