2

I'm trying to understand parameter passing in Java. There are some answers on Stackoverflow but they are not clear. The Evaluation Strategy page is very technical, so I don't understand it. This answer is helpful, but I don't understand the implications: Is Java “pass-by-reference” or “pass-by-value”?

I understand the Java uses Call by Sharing, but I'm not sure how its different from Call by Reference. I'm not sure if this is correct, can you check my answers?

Shared Steps
1) The main program calls a method and passes it an argument.
2) The expression in the argument is evaluated and its type is determined. The result is assigned to the Argument variable.

Call by Value

3) Without regard for type, a COPY of the Argument's VALUE is made and passed to the method.
4) The Formal Argument receives a variable containing a COPY of the Argument.
5) The Formal Argument makes changes to the copy.
6) The Actual Argument is UNCHANGED.

Call by Reference
3) Without regard for type, a COPY of the Argument's ADDRESS is made and passed to the method. 4) The Formal Argument receives an REFERENCE to the memory location of the Argument.
5) The Formal Argument and Actual Argument point to the same value. Both can modify the Value/Object.
6) The Method can mutate the Formal Argument WITHOUT LIMITATION. When the method ends, these changes will be seen in the Argument.

Call by Sharing (Java)
3) Without regard for type, a COPY of the Argument's ADDRESS is made and passed to the method.
4) ?
5) ?
6) ?

I know there is a difference between how Java treats primitive types and objects in parameter passing, can someone fill in these blanks by explaining why?

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
Code_Steel
  • 437
  • 2
  • 8
  • 14
  • 3
    There is absolutely no difference between how Java treats primitive types and reference types in parameter passing. – Sotirios Delimanolis Jun 23 '16 at 21:28
  • I meant that there are differences in how they behave. Can you explain these differences? – Code_Steel Jun 23 '16 at 21:36
  • 2
    There are no differences. Java handles values of both types the same way when passing them as arguments. – Sotirios Delimanolis Jun 23 '16 at 21:36
  • Maybe this link will help: http://stackoverflow.com/a/13907814/3086818 – Gennadii Saprykin Jun 23 '16 at 21:37
  • Also, are you asking what Java does or are you asking what the differences between these strategies are? Remove [tag:java] if it isn't relevant. – Sotirios Delimanolis Jun 23 '16 at 21:41
  • The Evaluation Strategy page also says `"However, the term "call by sharing" is not in common use; the terminology is inconsistent across different sources. "` and `"Call by sharing implies that values in the language are based on objects rather than primitive types, i.e. that all values are "boxed"."` It is certainly untrue that in Java all values are boxed. Java can box primitive values, but does not do so in all cases. – azurefrog Jun 23 '16 at 21:51
  • this is a [duplicate](https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value). java is pass by value. a *reference* is a primitive (the object it refers to is not). the value of the primitive is passed to functions. – Ray Tayek Jun 23 '16 at 21:35

2 Answers2

4

Call by Value means

  • the argument is evaluated before the method is called
  • the method receives a copy of the result of this evaluation
  • changes that are applied to the formal argument by the method are not visible to the caller

Call by Reference means

  • the argument is evaluated before the method is called
  • the method receives a reference to the result of this evaluation
  • changes that are applied to the formal argument by the method are visible to the caller

For now, I will skip Call by Sharing, since it does not have a clear meaning.

How it works in Java

  • the argument is evaluated before the method is called
  • the method receives a copy of the result of this evaluation
  • changes that are applied to the formal argument by the method are not visible to the caller

As you see, Java matches the Call by Value case. However, to really understand this, you have to understand how Java handles references. To do so, consider this class

public class Foo {
    private String value;

    public Foo(String value) {
        this.value = value;
    }

    public String get() {
        return value;
    }

    public void set(String value) {
        this.value = value;
    }
}

and this code snippet:

Foo actual = new Foo("foo");      // 1
                                  // 2
Foo formal = actual;              // 3
    formal.set("bar");            // 4
                                  // 5
actual.get(); // returns "bar"    // 6

As you can see, the changes to the object in formal have been applied to the object in actual, because formal points at the same object as actual. The assignment Foo formal = actual; did copy the reference, it did not copy the object.

Now, lets have a look at another code example:

Foo actual = new Foo("foo");      // 1
                                  // 2
Foo formal = actual;              // 3
    formal = new Foo("bar");      // 4
                                  // 5
actual.get(); // returns "foo"    // 6

As you can see, the changes to formal have not been applied to actual, because the reference in formal that points at the object in actual has been overwritten by a reference to a new object. The assignment Foo formal = actual; did copy the reference, it did not copy a pointer to actual.

Now, I talked about assignments, because I think this is perfectly clear for assignments. The point is now, that this is the exact same behavior for method calls: When the method is called, the evaluated actual argument is assigned to the formal argument, see line 3. However, the formal argument is not assigned back to the actual argument after the method is done, see line 5.

The reason why this is called Call by Sharing is, that you don't pass a deep copy of the actual argument. Thus, objects are shared between the caller and the callee. If an object contains mutable state, like Foo, then all changes that are applied to that mutable state in the method are visible to the caller. Please note the difference: Changes to the passed objects are visible, changing the reference target of the formal argument is not visible.

Lastly, a quick note about primitives: The code above does not need to be changed for primitives. This means, only the type Foo would be changed to e.g. boolean. Everything else is the same. Thus, the behavior is again the same as it is for an assignment: The value is copied. Since primitive values cannot contain mutable state, it is out of question that this is Call by Value.

Stefan Dollase
  • 4,530
  • 3
  • 27
  • 51
  • Thanks, Stefan. Can you please clarify the difference between Call by Reference and Call by whatever in Java. References are being passed in styles, but with Call by Reference, new object assignments to the formal argument are reflected in the Argument. Why? – Code_Steel Jun 23 '16 at 23:25
  • With call by reference, the second example would also return `"bar"`, because the assignment `Foo formal = actual;` would have copied a pointer to actual. Thus, the assignment `formal = new Foo("bar");` would have overwritten the value of `actual`. Does this make sense for you? – Stefan Dollase Jun 23 '16 at 23:41
  • I'm sorry I don't understand, I'm a noob. In Call by Reference, when a new object is assigned to the parameter, are you saying that the Formal Argument would also update the Actual Argument's reference? – Code_Steel Jun 24 '16 at 00:06
  • Java doesn't have call by reference (the capital letters are unnecessary). So the difference between call by reference and call by whatever (where "whatever" is "value") in Java is that Java doesn't have call by reference, but it does have call by whatever (where "whatever" is "value"). – Lew Bloch Jun 24 '16 at 00:19
  • Yes, but I do know that C# allows call by reference, so I'm trying to understand the difference between passing in C# and Java. – Code_Steel Jun 24 '16 at 00:21
  • Yes, that is what I meant to say. It does not fit my explanation with assignments very well, but I think you got it anyway. In languages that support call by reference, it is used for output parameters. You pass a variable to a method and the method can change the value of the variable. This is one way to implement multiple return values for one method, however it is also considered bad coding style. You might want to have a look at the C# `ref` and `out` keywords: http://stackoverflow.com/questions/388464/whats-the-difference-between-the-ref-and-out-keywords – Stefan Dollase Jun 24 '16 at 00:22
  • An alternative explanation for Call by Reference is to put `Foo actual = formal;` in line 5. The explanation in my previous comment assumes another assignment semantic, which makes it a pretty bad explanation. – Stefan Dollase Jun 24 '16 at 00:26
  • Yes, I've used `ref` and `out`, but I didn't understand why Java didn't allow them. I wanted to understand the difference in parameter passing in the two languages. I don't know if I understand it well, but thank you Stefan. – Code_Steel Jun 24 '16 at 00:26
  • `Foo formal = actual;` `formal.set("bar");` `Foo actual = formal;` So, when the method assigns a new object to formal, in call by reference all three lines above are executed but call by value does only the first two lines? – Code_Steel Jun 24 '16 at 00:29
  • @Code_Steel Yes, now you got it. Also, if you know how C# passes parameters, you already know how Java does it. It is pretty much the same. However, Java does not have non-primitive value-types aka structs. It also does not have `out` and `ref`. That is all. – Stefan Dollase Jun 24 '16 at 00:35
  • @ Stefan I understand now. Thank you very much. – Code_Steel Jun 24 '16 at 00:39
-1

My of understanding Call By Sharing is this:

With Value types, the actual value is directly copied, and the new copy is passed to the callee. The original value cannot be modified.

With Reference types, the actual reference to the value is copied, and the new copy is passed to the callee. The referenced object can be modified, but a re-allocation will not modify the original reference.

If you reallocate using the passed reference, you are creating a new object in the callee, and a return to the caller will reflect the originally-passed object. The object created in the callee should go out-of-scope and be marked for collection.

IgnusFast
  • 79
  • 7
  • The term "call by sharing" is not applicable. "the term "call by sharing" is not in common use; the terminology is inconsistent across different sources." per Wikipedia, https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing. – Lew Bloch Jun 24 '16 at 00:22
  • Really? I thought the name Call By Sharing made perfect sense. You're passing a reference to an object, but not THE reference. So while the called function can modify the original object, they can't create a new object and replace the original one... :) – IgnusFast Jun 24 '16 at 13:06