call by reference

R

rosty

I know there is no "call by reference" in Java. But please help me
convince two of my colleagues. We started learning Java about one
month ago, and they just don't believe me when i try to explain that
there is a confusion when passing reference types as an argumetn to a
function.

Please help. A link maybe to official documentation?

TIA
 
C

Chris Smith

rosty said:
I know there is no "call by reference" in Java. But please help me
convince two of my colleagues. We started learning Java about one
month ago, and they just don't believe me when i try to explain that
there is a confusion when passing reference types as an argumetn to a
function.

Please help. A link maybe to official documentation?

Well, the "official" reference would be JLS section 15.12.4.5, which
states:

Now a new activation frame is created, containing the target
reference (if any) and the argument values (if any), [...]

This can be verified experimentally:

class Test
{
private static void change(String s)
{
s = "New";
}

public static void main(String[] args)
{
String a = "Old";
change(a);
System.out.println(a);
}
}

This, of course, will print "Old" rather than "New", thus proving that
Java passes by value, even for reference types.

Most of the time, though, people who object to this fact *do* understand
the behavior of Java, and just have a fuzzy definition of "pass by
reference". When pressed, they will generally degrade to saying that
the meaning of "pass by reference" is language-specific, thus creating a
circular argument that you can't possibly disprove. Hopefully, they
will later come to their senses.

In any case, you might start by asking them whether the following
examples demonstrate pass by reference:

Example 1, in C:

void change(int *s)
{
*s = 7;
}

int main(int argc, char *argv[])
{
int a = 42;
change(&a);
printf("%i\n", a);

return 0;
}

Example 2, in Java:

import java.util.*;

class Test
{
private static Map m = new HashMap();

private static void change(String key)
{
m.put(key, "New");
}

public static void main(String[] args)
{
m.put("a", "Old");
change("a");
System.out.println(m.get("a"));
}
}

The answers to these two questions will give you an idea of what this
person thinks that "pass by reference" really means.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
G

George Cherry

Chris Smith said:
rosty said:
I know there is no "call by reference" in Java. But please help me
convince two of my colleagues. We started learning Java about one
month ago, and they just don't believe me when i try to explain that
there is a confusion when passing reference types as an argumetn to a
function.

Please help. A link maybe to official documentation?

Well, the "official" reference would be JLS section 15.12.4.5, which
states:

Now a new activation frame is created, containing the target
reference (if any) and the argument values (if any), [...]

This can be verified experimentally:

class Test
{
private static void change(String s)
{
s = "New";
}

public static void main(String[] args)
{
String a = "Old";
change(a);
System.out.println(a);
}
}

This, of course, will print "Old" rather than "New", thus proving that
Java passes by value, even for reference types.

Chris, I'm afraid your example will give rosty the wrong
notion that a called method can't change an object
when you pass the method the value of a reference
variable referring to the object? For example, rosty,
take a look at this:

class TestPassByValue2 {
private static void change(int[] a) {
a[0] = 4;
a[1] = 5;
a[2] = 6;
}

public static void main(String[] args) {
int[] intArray = new int[]{1, 2, 3};
change(intArray);
for (int i : intArray) {
System.out.print(i + " "); //Prints 4 5 6
}
}
}

George Cherry
 
C

Chris Smith

George Cherry said:
Chris, I'm afraid your example will give rosty the wrong
notion that a called method can't change an object
when you pass the method the value of a reference
variable referring to the object?

Only if rosty doesn't understand what's going on... which he said he
did. The point is that assigning to the formal parameter does not
affect the value of the actual parameter. In your code:

private static void change(int[] a) {
a[0] = 4;
a[1] = 5;
a[2] = 6;
}

In this case, you never assign to the formal parameter, so it doesn't
even matter if the parameter passing is by reference or by value. The
parameter just happens to identify some shared state, and you've
modified the shared state. This is exactly the same situation as my
"example 2" in the original post, and it doesn't demonstrate pass by
reference.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
T

Tor Iver Wilhelmsen

Please help. A link maybe to official documentation?

Java passes everything - primitives and object "references"/pointers -
by value.

Java does not have anything like C++'s reference concept. If you come
from C++, then Java does not have "pass by reference". C# does have it
though, but explicitly: In C# "struct"-originated objects are put on
the stack and passed by value, unless you use the "ref" keyword in the
method parameter declaration.
 
R

rosty

Thank you all! That's exactly what i was saying, but they would just not
listen. I'l show them this on monday. We'll see.
Chris Smith said:
George Cherry said:
Chris, I'm afraid your example will give rosty the wrong
notion that a called method can't change an object
when you pass the method the value of a reference
variable referring to the object?

Only if rosty doesn't understand what's going on... which he said he
did. The point is that assigning to the formal parameter does not
affect the value of the actual parameter. In your code:

private static void change(int[] a) {
a[0] = 4;
a[1] = 5;
a[2] = 6;
}

In this case, you never assign to the formal parameter, so it doesn't
even matter if the parameter passing is by reference or by value. The
parameter just happens to identify some shared state, and you've
modified the shared state. This is exactly the same situation as my
"example 2" in the original post, and it doesn't demonstrate pass by
reference.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
L

Lasse Reichstein Nielsen

I know there is no "call by reference" in Java. But please help me
convince two of my colleagues.

First, you must agree what "call by reference" means. The traditional
meaning is the passing of an "l-value". Assume for a second that
this function (in some unknown language) was called using
call-by-reference:
---
function cbrFunc(ref int x) {
x = 42;
}

int y = 37;
cbrFunc(y);
print(y); // prints 42.
---

That is, with call-by-reference, you pass a reference, not a value,
and you can change the value at the end of that reference. In this
example, the "y" and "x" variables are the same reference (also called
aliasing), and changing the value of one also changes the value of
the other.

With call-by-value, assigning a new value to a variable will never
change the value of another.

Now check what Java does. In no case will it allow you to take
the reference out of a variable, so that its value can be changed
without using the variable itself.

/L
 
D

Dale King

Chris said:
Most of the time, though, people who object to this fact *do* understand
the behavior of Java, and just have a fuzzy definition of "pass by
reference". When pressed, they will generally degrade to saying that
the meaning of "pass by reference" is language-specific, thus creating a
circular argument that you can't possibly disprove. Hopefully, they
will later come to their senses.

Actually I find that more often it is not understanding the difference
between the object living on the heap and the variable that refers to
it. When people say objects are passed by reference they are showing
this confusion.

Here is the canned response I put together on the subject:

Question:
Does Java pass objects by reference or by value?

Answer:
Since it makes no sense to begin any argument without agreed upon
defintions let's formally define our terms. I will use abstract
pseudocode to keep the issue from being clouded by the idiom of a
particular language. The source of my information is the book
"Advanced Programming Language Design" by Raphael A. Finkel.

For those unfamiliar with the term below an L-value is an expression
that can appear on the left side of an assignment statement. It is
basically a way to address where a variable is stored. Variables
and other ways to refer to locations in memory are L-values. Most
expressions are not L-values, e.g. ( x * 2 )

We assume the presence of a procedure named f that takes a formal
parameter s. We call that function giving it an actual parameter g.

The calling code:
f( g )

The function:
procedure f( s )
begin
-- body of the procedure
end;

There are several parameter passing semantics that have been
proposed or used:

value
The value of the actual parameter is copied into the formal
parameter when the procedure is invoked. Any modification of
the formal parameter affects only the formal parameter and
not the actual parameter. This is the most common form of
parameter passing and is the only one provided in C and Java.

result
The value of the formal parameter is copied into the actual
parameter when the procedure returns. Modifications to the
formal parameter do not affect the formal parameter until the
function returns. The actual parameter must be an L-value. It
is usually invalid to pass the same L-value to more than one
result parameter, but the compiler cannot always detect this.
The best example of this is out parameters in CORBA.

value result
Combination of value and result semantics. The best example of
this are inout parameters in CORBA.

reference
The L-value of the formal parameter is set to the L-value of the
actual parameter. In other words, the address of the formal
parameter is the same as the address of the actual parameter. Any
modifications to the formal parameter also immediately affect the
actual parameter. FORTRAN only has reference mode (expressions are
evaluated and stored in a temporary location in order to obtain an
L-value). C++ has reference parameters by putting a & before the
formal parameter name in the function header. Reference mode can
be simulated in C using pointers and adding the & to the actual
parameter and dereferencing the formal parameter within the
function.

readonly
Can use either value or reference mode, but modification of the
formal parameter is forbidden by the compiler.

macro
name
These two have been used in the past, but are very much out of favor
because they are confusing and difficult to implement. Therefore I
won't bother trying to explain them.

Now that we have some definitions of terms we can return to the
question. Does Java pass objects by reference or by value?

The answer is NO! The fact is that Java has no facility whatsoever
to pass an object to any function! The reason is that Java has no
variables that contain objects.

The reason there is so much confusion is people tend to blur the
distinction between an object reference variable and an object
instance. All object instances in Java are allocated on the heap
and can only be accessed through object references. So if I have
the following:

StringBuffer g = new StringBuffer( "Hello" );

The variable g does not contain the string "Hello", it contains a
reference (or pointer) to an object instance that contains the
string "hello".

So if I then call f( g ), f is free to modify its formal parameter s
to make it point to another StringBuffer or to set it to null. The
function f could also modify the StringBuffer by appending " World"
for instance. While this changes the value of that StringBuffer, the
value of that StringBuffer is NOT the value of the actual parameter.

Imagine for instance if I set g to null before passing it to f. There
is no StringBuffer now to modify and f can in no way change the value
of g to be non-null.

The bottom line is Java only has variables that hold primitives or
object references. Both are passed by value.
 
M

Mike Schilling

rosty said:
I know there is no "call by reference" in Java. But please help me
convince two of my colleagues. We started learning Java about one
month ago, and they just don't believe me when i try to explain that
there is a confusion when passing reference types as an argumetn to a
function.

Please help. A link maybe to official documentation?


The best discussion of this I know of is at
http://www.yoda.arachsys.com/java/passing.html .
 
G

George Cherry

Chris Smith said:
rosty said:
I know there is no "call by reference" in Java. But please help me
convince two of my colleagues. We started learning Java about one
month ago, and they just don't believe me when i try to explain that
there is a confusion when passing reference types as an argumetn to a
function.

Please help. A link maybe to official documentation?

Well, the "official" reference would be JLS section 15.12.4.5, which
states:

Now a new activation frame is created, containing the target
reference (if any) and the argument values (if any), [...]

This can be verified experimentally:

class Test
{
private static void change(String s)
{
s = "New";
}

public static void main(String[] args)
{
String a = "Old";
change(a);
System.out.println(a);
}
}

This, of course, will print "Old" rather than "New", thus proving that
Java passes by value, even for reference types.

rosty:

The following code, of course, prints "New" rather than "Old".
It's important to realize that passing the value of a reference
variable (which points to an object on the heap) allows the
called method to change the object on the heap. But, of course,
the called method can't change the value of the caller's
actual parameter (which continues to point at the same object
on the heap). But note that String objects are immutable, so
the object pointed to by "a" in Chris's example can't be
changed--ever. I wonder therefore whether Chris's example
is, well, well, pedagogically effective??? : o )

class TestPassByValue3 {
private static void change(StringBuilder s) {
s.replace(0, 3, "New");
}

public static void main(String[] args) {
StringBuilder a = new StringBuilder("Old");
change(a);
System.out.println(a);
}
}

George W. Cherry
 
T

Tor Iver Wilhelmsen

George Cherry said:
But note that String objects are immutable, so
the object pointed to by "a" in Chris's example can't be
changed--ever. I wonder therefore whether Chris's example
is, well, well, pedagogically effective??? : o )

What adds confusion is that String has a few methods that might look
like they modify the String, but they just return new Strings based on
the String in question, e.g. someString.trim().
 
C

ChrisWSU

i had similiar argument with my fellow employees on pass by value vs
pass by reference. I actually pasted lil papers on the subject on
their computers like the one at:
http://javadude.com/articles/passbyvalue.htm

do a google search on "java pass value" and u will get a lot. We
actually have problems with the professors teaching it wrong...
 
J

John C. Bollinger

Dale said:
Here is the canned response I put together on the subject:

A very nice explanation, Dale. I feel compelled to raise one nitpick,
however (not even Java-related):

[...]
There are several parameter passing semantics that have been
proposed or used:

value
The value of the actual parameter is copied into the formal
parameter when the procedure is invoked. Any modification of
the formal parameter affects only the formal parameter and
not the actual parameter. This is the most common form of
parameter passing and is the only one provided in C and Java.

result
The value of the formal parameter is copied into the actual
parameter when the procedure returns. Modifications to the
formal parameter do not affect the formal parameter until the
function returns. The actual parameter must be an L-value. It
is usually invalid to pass the same L-value to more than one
result parameter, but the compiler cannot always detect this.
The best example of this is out parameters in CORBA.

value result
Combination of value and result semantics. The best example of
this are inout parameters in CORBA.

reference
The L-value of the formal parameter is set to the L-value of the
actual parameter. In other words, the address of the formal
parameter is the same as the address of the actual parameter. Any
modifications to the formal parameter also immediately affect the
actual parameter. FORTRAN only has reference mode (expressions are
evaluated and stored in a temporary location in order to obtain an
L-value).

Fortran is in fact not restricted to any particular argument passing
mode. It specifies the semantics of subprogram calls, including effects
on subprogram arguments that are often implemented by compilers by means
of pass by reference, but that can also be implemented with value-result
(a.k.a copy in / copy out) in general, or with value or result
techniques in some specific cases. Fortran compilers exist, I believe,
that will choose among all these depending on the characteristics of the
subprogram involved. They are unquestionably free to do so.
 
C

Chris Smith

John C. Bollinger said:
Fortran is in fact not restricted to any particular argument passing
mode. It specifies the semantics of subprogram calls, including effects
on subprogram arguments that are often implemented by compilers by means
of pass by reference, but that can also be implemented with value-result
(a.k.a copy in / copy out) in general, or with value or result
techniques in some specific cases. Fortran compilers exist, I believe,
that will choose among all these depending on the characteristics of the
subprogram involved. They are unquestionably free to do so.

If this is true, it's certainly interesting. Are you sure? It's worth
clarifying that passing by reference versus value-result are not
implementation choices; they are only different because they have
specific observable differences in behavior.

For example, C++ uses pass by reference, NOT value-result. That means
that this C++ code:

int a = 0;

void test(int& p)
{
p = 7;
cout << a << endl;
}

int main(int argc, char *argv[])
{
test(a);
return 0;
}

will print '7', and NOT '5'.

Is the behavior of similar code in FORTRAN really undefined? It's also
possible to imagine a language in which the difference between pass by
reference and pass by value-result is not observable. Is FORTRAN such a
language?

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
M

Mike Schilling

Chris Smith said:
If this is true, it's certainly interesting. Are you sure? It's worth
clarifying that passing by reference versus value-result are not
implementation choices; they are only different because they have
specific observable differences in behavior.

Yes, John is correct. Value-result was used in the IBM mainframe compilers,
and its side effects are used widely in mainframe programs, which is
probably where you got the impression that it's "standard". FORTRAN on,
say, PDP-11s used pass-by-reference. Portability was much less of an issue
in those days than it is now.

As "Real Programmers Don't Use Pascal" reminds us:

The only parameter passing mechanism endorsed by Real
Programmers is call-by-value-return, as implemented in the
IBM/370 Fortran G and H compilers
 
R

rosty

rosty:

The following code, of course, prints "New" rather than "Old".
It's important to realize that passing the value of a reference
variable (which points to an object on the heap) allows the
called method to change the object on the heap.
That's exactly what my coleagues are saying. So, they conclude, it is a "by
reference" call.
But, of course,
the called method can't change the value of the caller's
actual parameter (which continues to point at the same object
on the heap).
And this is what I am saying.

So is it correct to call that "call by reference" or "call by value"? That
is the question.
 
P

Pete Barrett

So is it correct to call that "call by reference" or "call by value"? That
is the question.
I think I disagree with that. As far as I can see, the important
question is not "what is the correct thing to call it?", but "what can
I do to the object from the function it's been passed to?" My guess is
that your colleagues know the answer to the second question pretty
well, but are a little hazy on the precise definition of the terms
"pass by reference" and "pass by value", as Chris Smith suggests.

And it's precisely this sort of distinction which high level languages
are supposed to shield us from. The explanations as to the difference
between the two methods in earlier posts from Dale King have focussed
on the difference between locations in memory and what they refer to,
or (at a slightly higher and more formal level) the concept of
L-values - all this is essential to a compiler writer, but a simple
user of the language shouldn't really need to know how the language is
implemented at that level of detail.

Pete Barrett
 
B

blmblm

John C. Bollinger said:
Fortran is in fact not restricted to any particular argument passing
mode. It specifies the semantics of subprogram calls, including effects
on subprogram arguments that are often implemented by compilers by means
of pass by reference, but that can also be implemented with value-result
(a.k.a copy in / copy out) in general, or with value or result
techniques in some specific cases. Fortran compilers exist, I believe,
that will choose among all these depending on the characteristics of the
subprogram involved. They are unquestionably free to do so.

If this is true, it's certainly interesting. Are you sure? It's worth
clarifying that passing by reference versus value-result are not
implementation choices; they are only different because they have
specific observable differences in behavior.

For example, C++ uses pass by reference, NOT value-result. That means
that this C++ code:

int a = 0;

void test(int& p)
{
p = 7;
cout << a << endl;
}

int main(int argc, char *argv[])
{
test(a);
return 0;
}

will print '7', and NOT '5'.

Is the behavior of similar code in FORTRAN really undefined? It's also
possible to imagine a language in which the difference between pass by
reference and pass by value-result is not observable. Is FORTRAN such a
language?

It might well be undefined. As I understand it, one of the things
that historically contributed to there being better compilers for
FORTRAN (in the sense of "producing faster code") was that there were
certain restrictions on parameter passing. One of them is (was?
I only checked the FORTRAN 77 standard, but my guess is that this
hasn't changed in newer standards) that if subroutine FOO has two
array arguments A and B, you're not allowed to write "CALL FOO(C, C)"
if FOO modifies anything in A or B. If you do, the program is "not
standard-conforming", and the compiler is allowed to do whatever it
pleases. (The standard joke here, I believe, is "including starting
WW III".) A similar restriction applies to calling FOO with a variable
that's also accessible via a common block, which I think that's the
nearest equivalent to your code above. If so, then your program would
not be standard-conforming, so the compiler can ....

The folks over in comp.lang.fortran could no doubt provide a definitive
and current answer. I'd cross-post, but I've never been quite sure
about when it was okay to do so from an existing thread ....
 
B

blmblm

I think I disagree with that. As far as I can see, the important
question is not "what is the correct thing to call it?", but "what can
I do to the object from the function it's been passed to?" My guess is
that your colleagues know the answer to the second question pretty
well, but are a little hazy on the precise definition of the terms
"pass by reference" and "pass by value", as Chris Smith suggests.

You have a point, but if saying "Java has call by reference" makes
them think they can change passed-in object references as well as
the objects to which they point -- since this would be possible in
other languages that have something called "call by reference" --
well, that's not so good.
And it's precisely this sort of distinction which high level languages
are supposed to shield us from. The explanations as to the difference
between the two methods in earlier posts from Dale King have focussed
on the difference between locations in memory and what they refer to,
or (at a slightly higher and more formal level) the concept of
L-values - all this is essential to a compiler writer, but a simple
user of the language shouldn't really need to know how the language is
implemented at that level of detail.

This sounds good too, but I know that many things about Java made more
sense to me when I understood that Java has two kinds of variables,
primitives and references, and if you declare var1 as "Object var1",
var1 is not an Object *but a reference to an Object*. Once I started
thinking in this way, a lot of stuff that had previously seemed
strange ("new Object[10]" doesn't actually create 10 Objects, e.g.,
and "Object var2 = var1" doesn't make a copy of var1) suddenly made
perfect sense.

"YMMV", maybe. Or maybe this isn't the kind of thing you meant when
you said that HLLs are supposed to shield us from details.
 
C

Chris Smith

Mike Schilling said:
Yes, John is correct. Value-result was used in the IBM mainframe compilers,
and its side effects are used widely in mainframe programs, which is
probably where you got the impression that it's "standard". FORTRAN on,
say, PDP-11s used pass-by-reference. Portability was much less of an issue
in those days than it is now.

Nah, I didn't get any impressions from anything except John's post. I
don't know FORTRAN at all. I just wanted to clarify that we are
properly talking about calling conventions and their observable
results... not about implementation details.

Looks like John is correct, and I am very interested in this.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top