Trouble with Java concepts

F

FET

Hello everyone,
I am slightly confused here. Here is some code:

public class samp{


public int f(StringBuffer str){
if(str == null)
str = new StringBuffer(10);
str.append("inside f");

return 0;
}

public static void main(String args[]){
samp obj = new samp();
StringBuffer str = null
obj.f(str);
System.out.println(str);
}
}

If I run the code above, the System.out.println line prints null. If
however, I allocate a new StringBuffer(10) in main() instead of
assigning it null, then it prints "inside f".

If I replace all StringBuffer with String, it prints null, no matter
where it gets initialized.

My problem is I am not able to explain this behaviour. Can someone
please explain why this is so ?

Thanks in advance.

Best Regards.
 
G

Guest

FET said:
Hello everyone,
I am slightly confused here. Here is some code:

public class samp{


public int f(StringBuffer str){
if(str == null)
str = new StringBuffer(10);
str.append("inside f");

return 0;
}

public static void main(String args[]){
samp obj = new samp();
StringBuffer str = null
obj.f(str);
System.out.println(str);
}
}

If I run the code above, the System.out.println line prints null. If
however, I allocate a new StringBuffer(10) in main() instead of
assigning it null, then it prints "inside f".

If I replace all StringBuffer with String, it prints null, no matter
where it gets initialized.

My problem is I am not able to explain this behaviour. Can someone
please explain why this is so ?

In Java every parameter passing is by value.
In your example the str reference in main is equal to null
and it will not be changed in any manner by obj.f invocation:
it will remain null.

Your obj.f invocation:
obj.f(str);
may effectevely be rewrite as:
obj.f(null);

Even your System.out.println invocation:
System.out.println(str);
may effectevely be rewrite as:
System.out.println(null);

- Dario
 
T

Tim Ward

FET said:
Hello everyone,
I am slightly confused here. Here is some code:

public class samp{


public int f(StringBuffer str){
if(str == null)
str = new StringBuffer(10);
str.append("inside f");

return 0;
}

public static void main(String args[]){
samp obj = new samp();
StringBuffer str = null
obj.f(str);
System.out.println(str);
}
}

If I run the code above, the System.out.println line prints null. If
however, I allocate a new StringBuffer(10) in main() instead of
assigning it null, then it prints "inside f".

If I replace all StringBuffer with String, it prints null, no matter
where it gets initialized.

My problem is I am not able to explain this behaviour. Can someone
please explain why this is so ?

Parameter passing is by value. The parameter to f (which happens to be a
reference) is copied, so main's str is copied to f's str when the call is
made. Assignment to the copy inside f makes no difference to the variable it
was copied from, the variable str in main.
 
G

Gorf

Tim Ward said:
FET said:
Hello everyone,
I am slightly confused here. Here is some code:

public class samp{


public int f(StringBuffer str){
if(str == null)
str = new StringBuffer(10);
str.append("inside f");

return 0;
}

public static void main(String args[]){
samp obj = new samp();
StringBuffer str = null
obj.f(str);
System.out.println(str);
}
}

If I run the code above, the System.out.println line prints null. If
however, I allocate a new StringBuffer(10) in main() instead of
assigning it null, then it prints "inside f".

If I replace all StringBuffer with String, it prints null, no matter
where it gets initialized.

My problem is I am not able to explain this behaviour. Can someone
please explain why this is so ?

Parameter passing is by value. The parameter to f (which happens to be a
reference) is copied, so main's str is copied to f's str when the call is
made. Assignment to the copy inside f makes no difference to the variable it
was copied from, the variable str in main.

Indeed.

For a more thorough explanation:

http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
 
J

Jim Cochrane

FET said:
Hello everyone,
I am slightly confused here. Here is some code:

public class samp{


public int f(StringBuffer str){
if(str == null)
str = new StringBuffer(10);
str.append("inside f");

return 0;
}

public static void main(String args[]){
samp obj = new samp();
StringBuffer str = null
obj.f(str);
System.out.println(str);
}
}

If I run the code above, the System.out.println line prints null. If
however, I allocate a new StringBuffer(10) in main() instead of
assigning it null, then it prints "inside f".

If I replace all StringBuffer with String, it prints null, no matter
where it gets initialized.

My problem is I am not able to explain this behaviour. Can someone
please explain why this is so ?

In Java every parameter passing is by value.

Actually, the conventional meaning of pass by value is to pass a copy (as
in pass by value in the C language), but this is not the case here, so what
you said could be misleading to the OP*. To show that it is not by value,
here is a modified version of the OP's post:

public class samp2 {

public int f(StringBuffer str){
if(str == null)
str = new StringBuffer(10);
str.append("inside f");

return 0;
}

public static void main(String args[]){
samp2 obj = new samp2();
StringBuffer str = new StringBuffer("Start - ");
obj.f(str);
System.out.println(str);
}
}

If str was passed by value, one would expect the output to be:
Start -

but since it's not, the output is:

Start - inside f

In main, 'str' is attached to a StringBuffer object. obj.f(str)
passes a reference to that object (not a copy of the object), so that
the object created in main is changed by the call to f. However,
in the original code, the "object" being passed is 'null'. This is
different from passing a reference to an object and having f change it.
Instead, since str == null, f creates a new object and attaches it to its
'str'. However, changing the 'str' variable in f - attaching it to a
new object - does not change the 'str' variable in main. Thus
when str == null the 'null' object will not be changed in main. (Of
course, a 'null' "object" can't be changed, but that's a separate issue.)

This is different from changing the object to which 'str' is attached,
which happens in my modified example.

* Since you said: "In Java every parameter passing is by value.", I think
you are implying the same thing that I'm saying, but I suspect that the
wording could confuse the OP into thinking that arguments are passed by
value in Java - that is, copied.
 
P

P.Hill

Jim said:
Actually, the conventional meaning of pass by value is to pass a copy (as
in pass by value in the C language),

Jim,

There seems to be this weird pedantic subset of Java programmers who insist
that "passing" does not always include putting the value of something on
the stack, so don't want to say "objects are passed by reference", but
insist until they turn blue and red in the face that we all should
say "pass the value of the reference to the object", which to me clarifys
nothing and means exactly the same thing.

Edsger Dijkstra is probably rolling in his grave!

"My area of interest focuses on the streamlining of the mathematical argument so
as to increase our powers of reasoning, in particular, by the use of formal
techniques." -- Edsger Dijkstra

That is the long way to say you probably just scratched something that
is going to ooze for a while, so I suggest you don't scratch it again.

The imporant idea for the OP is that an object variable contains a reference
to an object, so assigning a new obejct to a local variable makes it reference
the new object leaving any old reference that was used to create a local
variable from a parameter to point at whatever it was pointing originally.

-Paul
 
R

Roedy Green

There seems to be this weird pedantic subset of Java programmers who insist
that "passing" does not always include putting the value of something on
the stack, so don't want to say "objects are passed by reference", but
insist until they turn blue and red in the face that we all should
say "pass the value of the reference to the ob

Us "weird folk" each in our own way figured it out. Then we tried to
explain it to others. We discovered by trial and error that being very
rigid that Java always passes by value is the fastest route to getting
someone to understand how it all works. We came to a consensus on
this in this very newsgroup.

See http://mindprod.com/jgloss/callbyvalue.html

That is why we sometimes get so angry when people muddy the waters
with alternate explanations especially when you redefine Java
terminology in some non-standard way.

It is especially confusing for people who come from a C++ background
who expect Java to work the same way.
 
P

P.Hill

Roedy said:

A pretty good definition by the way.
It is especially confusing for people who come from a C++ background
who expect Java to work the same way.

No it's easy for C++ programmers. There are only references in Java
there are NO pointers there are NO local (stack) objects, so there is no need
for & (reference), * (pointer) and plain object syntax. Since there are only
references when you see a variable which names an object in Java think of it as
being very much like a C++ definition with & on it; it's a typed reference in
all cases.

A further simplification of syntax applies to . (dot) and -> (arrow); the
designers of Java needed just one, they used dot, though the meaning is the
equivalent of the C++ -> (arrow).

I see it as depending on a strong understanding of an object reference, not
on playing with the existing meaning of "pass-by-value". I suppose if I went
down to my local community college and tried this on some beginners I might
be more wishy washing on the subject. To each his own.

-Paul
 
R

Roedy Green

No it's easy for C++ programmers. There are only references in Java
there are NO pointers there are NO local (stack) objects, so there is no need
for & (reference), * (pointer) and plain object syntax. Since there are only
references when you see a variable which names an object in Java think of it as
being very much like a C++ definition with & on it; it's a typed reference in
all cases.

But they don't tell the incoming C++ programmer such as myself that,
at least they did not used to. You went scavenging around trying to
figure out how you accomplished all the usual memory allocation and
addressing dodges, not realising they were GONE. Further, it was a
VERY GOOD THING.

If someone were devising a control system for an automobile today from
scratch, likely it would look more like a joystick. Someone coming to
use it for the first time would search for the clutch, the steering
wheel, the brakes, the gear shift, the accelerator pedal... We think
of that old system as simple only because it is familiar and we forgot
the trauma of our early driving and parking lessons.

In like manner, someone coming to Java from C++ tends to look around
for the old manual controls that are now automatic, and feels that
something must be seriously wrong when he can't find them. It takes a
while to trust the automatic stuff to work without your diligent
minstrations. After spending so many years forced to tinker with it,
it seems odd to have time to focus on other aspects of programming
such as the algorithms or choosing the best Collection for a given
task.
 
S

Steve Horsley

Roedy said:
But they don't tell the incoming C++ programmer such as myself that,
at least they did not used to. You went scavenging around trying to
figure out how you accomplished all the usual memory allocation and
addressing dodges, not realising they were GONE. Further, it was a
VERY GOOD THING.

I would try to explain to an incoming C/C++ programmer that passing objects
is functionally identical to passing pointers in C. Except that since the
use of pointers is implicit (you cannot have an Object, only a reference)
there is no need for the java syntax to constantly mention the fact that the
reference is being used. Thus, you could pretty-much convert java to C by
replacing "." with "->" and putting a "*" before all object (i.e. non-
primitive) variable definitions.

All java objects are on the heap.
There is no equivalent of a stack-based object in java.
The clue is the use of "new".

Like this:

java C

Thing t = new Thing(); Thing *t = new Thing();
int i = t.getValue(); int i = t->getValue();
int j = t.value; int j = t->value;
// impossible Thing t; // stack resident object
t = null; t = (void*) 0;
t.getValue(); t->getValue();

Steve
 
M

Michael Borgwardt

Which is exactly what Java does: pass a copy of the reference value, which
is exactly the reason why the OP's program does not work the way he thinks
it should.
There seems to be this weird pedantic subset of Java programmers who insist
that "passing" does not always include putting the value of something on
the stack, so don't want to say "objects are passed by reference", but
insist until they turn blue and red in the face that we all should
say "pass the value of the reference to the object", which to me clarifys
nothing and means exactly the same thing.

I thought like that as well at one point, but eventually came around to be
one of those pedants as well - being pedantic is the most essential part
of being a good programmer.

The point is that "pass by reference" has a very narrow traditional meaning,
namely one that would allow the OP's program to work as expected - and Java
simply doesn't work that way: assigning something to a passed parameter does
not change its value outside the method call.
 
P

P.Hill

Michael said:
Which is exactly what Java does: pass a copy of the reference value, which
is exactly the reason why the OP's program does not work the way he thinks
it should.

Yes, we have gotten off topic.
I thought like that as well at one point, but eventually came around to be
one of those pedants as well - being pedantic is the most essential part
of being a good programmer.

You choose your pedanticness, I'll choose mine :)
The point is that "pass by reference" has a very narrow traditional
meaning,
namely one that would allow the OP's program to work as expected

No it wouldn't. He reassinged the reference that had been passed.
Any language that has pass by reference would demonstrate the same behavior.
simply doesn't work that way: assigning something to a passed parameter
does
not change its value outside the method call.

Oh, and in what commonly used production language does reassigning the value
of the parameter which was passed change the original? None which I know of.

I still maintain that the primary idea is that the OP needs to understand what
Foo f1; means in Java. It is a reference.
So is the f2 in
void bar( Foo f2 );
but it is a different reference, and is also not a reference to a reference
to a Foo.

whatever,
-Paul
 
C

Carl Howells

P.Hill said:
Oh, and in what commonly used production language does reassigning the
value
of the parameter which was passed change the original? None which I
know of.

Umm... C++? When using pass-by-reference?

#include <stdio.h>

void make_five(int &i)
{
i = 5;
}

int main(int argc, char** argv)
{
int j = 15;
printf("Before: %d\n", j);
make_five(j);
printf("After: %d\n", j);
return 0;
}

*That*, by the way, is pass-by-reference. Very different from what java
has, which is pass-by-value.
 
L

Lance Lamboy

Umm... C++? When using pass-by-reference?

#include <stdio.h>

void make_five(int &i)
{
i = 5;
}
}
int main(int argc, char** argv)
{
int j = 15;
printf("Before: %d\n", j);
make_five(j);
printf("After: %d\n", j);
return 0;
}
}
*That*, by the way, is pass-by-reference. Very different from what java
has, which is pass-by-value.

I am a little rusty on my C++ so I may be getting this all wrong, but
isn't the argument to make_five an int pointer. You're not changing the
int pointer, only the int that it is pointing to.

You could do the same thing in java with

public void make_five ( int [ ] i )
{
i [ 0 ] = 5 ;
}
 
C

Carl Howells

Lance said:
I am a little rusty on my C++ so I may be getting this all wrong, but
isn't the argument to make_five an int pointer. You're not changing the
int pointer, only the int that it is pointing to.

You're confusing implementation with definition. Yeah,
pass-by-reference in C++ tends to be implemented using a hidden
pointer... But it doesn't necessarily have to be.
You could do the same thing in java with

public void make_five ( int [ ] i )
{
i [ 0 ] = 5 ;
}

Um... No. Not the same at all. Look at the way the types are declared.

In the C++ example I gave, "j" is passed to the function. "j" happens
to be a variable that is declared as an int. When the function returns,
the value that is stored in "j" is different.

In the java example you gave, you would have to pass in a variable that
was typed as "int []", rather than "int". The function changes the
value of one of the elements of the int [], but when it returns, the
value actually passed in, the "int []", still has the same value it did
before the call.

The two are VERY different semantically.
 
C

Chris Smith

Lance said:
I am a little rusty on my C++ so I may be getting this all wrong, but
isn't the argument to make_five an int pointer. You're not changing the
int pointer, only the int that it is pointing to.

No. The argument to make_five is an int passed by reference (in C++
terms, but inconsistent with the definition of pass-by-reference, it's
also called a reference to an int). In short, it's another name for
accessing the same int as in the calling context. This might be
implemented using an int pointer (or it might not), but it's certainly
not a pointer from the perspective of the language.

Of course, you could always make up arbitrarily complex mental models
for justifying the application of any call terminology to any language,
but luckily the standard definitions of terms specify a kind of litmus
test; what does it mean if an identifier occurs on the receiving side of
the language's standard (i.e., unmodified by things like operator
overloading) assignment operator. In Java's case, that means changing a
reference, so the reference is the main thing, and the argument (a
reference) is passed by value. In the C++ code above, that means
changing the value of the int, so the int is the main thing, and it's
passed by reference.

The duplication of the term 'reference', which has subtly different
meanings in all three contexts (Java, C++, and standard definitions of
call methods) generates confusion, certainly; but not as much as
confusing the issue and causing false expectations like the one that
started this thread, by claiming that Java passes by reference. And at
least when you do understand the right answer, you know that it's right.
You could do the same thing in java with

public void make_five ( int [ ] i )
{
i [ 0 ] = 5 ;
}

Except that in this case, the argument is 'i', and saying 'i = ...' will
not change that int; so the int is not being directly passed. You're
only passing enough information to indirectly locate the int (if you
also know where to look; meaning the first array slot). That's no
different, fundamentally, from passing a String that's used to look up
some object in a globally accessible HashMap, or any other kind of
indirect access. You have to stop somewhere before all the words lose
their meaning. The assignment operator designates the well-defined
stopping point.

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

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

Roedy Green

You choose your pedanticness, I'll choose mine :)

Not really. To communicate, you must share the conventions of those
you speak with. If your pedanticity is too out of alignment with
those you are talking with, they will misunderstand you.

One of the big problems I run into on the net is mistaking newbies for
experts and vice versa, and giving them an inappropriate answer.


If I think someone is a newbie, I don't take their questions very
literally. I just try to guess which frequently asked question they
are beating around.
 
P

P.Hill

Chris said:
In Java's case, that means changing a
reference, so the reference is the main thing, and the argument (a
reference) is passed by value. In the C++ code above, that means
changing the value of the int, so the int is the main thing, and it's
passed by reference.

Chris, you are actually starting to make sense. After visiting
this pedantic terminology again after not caring about it for a few years, maybe
I'm willing to embarce the more pedantic terminology. Despite the problems
with the C++ example shown, I see where some people seem to be confused.

I am reminded by this example that there is more than one type of
assignment in C++. Oh the joys and fun of C++!

-Paul
 
J

Jim Cochrane

Umm... C++? When using pass-by-reference?

#include <stdio.h>

void make_five(int &i)
{
i = 5;
}

int main(int argc, char** argv)
{
int j = 15;
printf("Before: %d\n", j);
make_five(j);
printf("After: %d\n", j);
return 0;
}

*That*, by the way, is pass-by-reference. Very different from what java
has, which is pass-by-value.

Do newbies ever get confused by the "pass-by-value" terminology and think
that it means that the object being referred to is passed by value (i.e.,
that a copy of the object is passed, so that the original cannot be
changed)? If so, then perhaps a new terminology (not using "by value" or
"by reference") would be less confusing. If not then, I guess IIABDFI
(If it ain't broke, don't fix it.).
 

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

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,270
Latest member
TopCryptoTwitterChannels_

Latest Threads

Top