Strings...immutable?

M

Mike Schilling

Wojtek said:
Gordon Beaton wrote :
Yes, but the use of pointers is hidden from view. If you use
pointers, then you should be able to have an array of pointers.

This is how you declare an array of pointers in Java:

Object[] array;
Which means that you should be able to do pointer arithmetic.

That isn't a logical conclusion of the preceding statement.
So while yes Java uses pointers beneath the hood, they are not
exposed to the developer.

Just because Java doesn't offer the same set of pointer operations
that say, C does, doesn't mean that Java doesn't have pointers.

Sure Java has pointers. But they are not exposed to the developer.

Sure they are. It's *objects* that are not exposed to the developer :)
Java doesn't let you access an object directly: A Java developer (unlike a
C++ developer) can't create a local or static object, or pass an object by
value to a called method. The only thing Java lets you do with objects is
access them indirectly, via a pointer. And where a C++ object can de
defined to contain another object, all a Java object can contain is a
*pointer* to another object. Java uses the dot (".") to access fields and
methods, but it has the same meaning as C++'s arrow ("->").
 
W

Wojtek

Patricia Shanahan wrote :
Wojtek said:
Patricia Shanahan wrote :


Yes, but the use of pointers is hidden from view. If you use pointers, then
you should be able to have an array of pointers. Which means that you
should be able to do pointer arithmetic.

A Java String[] is an array of pointers.

Pointer arithmetic, if available, can be used to construct array access.
However, that is rather like saying "A general GOTO can be used to build
structured statement organizations such as if-then-else."

A language can provide array access, including access to arrays of
pointers, without providing pointer arithmetic, just as easily as a
language can support if-then-else without having a general GOTO.

There is a difference between array access using indexes and array
access using pointers in the syntax. Yes, underneath the hood both
methods resolve to the same code, but the visible syntax is different,
and either method is used to illustrate the access method to ease
understanding of what is being done.

Or you can set a pointer to the beginning of the array, and then add 1
to it to move to the next element. In the code you are directly
accessing the second element.

I realize that in Java you can set a reference to the second element in
the array and then use that. But you cannot directly move that
reference to the third element. You can set it by using an index to the
thrid element.
I'm not at all sure what this means. It is the fact that a Java
reference "points" in the sense of identifying an object makes it a pointer.


How do you classify the parameter passing in the call to myMethod in the
following program? Call by reference? Call by value? Call by name? Or what?

I consider it to be call by value, where the parameter myBuf is a
pointer to the StringBuffer instantiated in main.

No it is a call by reference. If it was a call by value, then a clone
of the StringBuffer (in the following code) would be placed in the
stack. The method would then use the clone and the calling main() would
still use its private copy.

Types (objects) are passed by reference value. Primitives (int, long)
are passed by value.

Ok, let's take this apart.

1> public class CallByQuestion {
2> static StringBuffer x;
3> public static void main(String[] args) {
4> StringBuffer myBuf = new StringBuffer();
5> x = myBuf;
6> System.out.println("Before call:");
7> System.out.printf(" x==myBuf is %b%n",x==myBuf);
8> System.out.printf(" myBuf contents: %s%n", myBuf.toString());
9> myMethod(myBuf);
10> System.out.println("After call:");
11> System.out.printf(" x==myBuf is %b%n",x==myBuf);
12> System.out.printf(" myBuf contents: %s%n", myBuf.toString());
13> }
14>
15> private static void myMethod(StringBuffer myBuf) {
16> StringBuffer y = myBuf;
17> myBuf = new StringBuffer("Some data");
18> System.out.println("Inside myMethod:");
19> System.out.printf(" x==myBuf is %b%n",x==myBuf);
20> System.out.printf(" myBuf contents: %s%n", myBuf.toString());
21> y.append("Some other data");
22> }
23> }
More generally, how would you go about predicting and explaining the
output from the program?

2 - x is a static reference to a StringBuffer, set to null
4 - myBuf gets a reference to a StringBuffer(1) object
5 - x has a reference to the same StringBuffer(1) as myBuf
9 - myMethod is called passing in a reference to myBuf
15 - myMethod starts up with a reference to StringBuffer(1)

Note that the myBuf in the myMethod parameter is a different reference
variable than the myBuf in main(), and is in fact private to myMethod()

16 - y gets a reference to StringBuffer(1)
17 - myBuf now references a new StringBuffer(2)
21 - the StringBuffer(1) references by y has a String appended to it.

Since myBuf in myMethod is private to myMethod, then of course x==myBuf
in myMethod is false since they are referencing two different objects.
 
W

Wojtek

Mike Schilling wrote :
Wojtek said:
Gordon Beaton wrote :
On Tue, 20 Mar 2007 14:00:37 GMT, Wojtek wrote:
Yes, but the use of pointers is hidden from view. If you use
pointers, then you should be able to have an array of pointers.

This is how you declare an array of pointers in Java:

Object[] array;

Which means that you should be able to do pointer arithmetic.

That isn't a logical conclusion of the preceding statement.

So while yes Java uses pointers beneath the hood, they are not
exposed to the developer.

Just because Java doesn't offer the same set of pointer operations
that say, C does, doesn't mean that Java doesn't have pointers.

Sure Java has pointers. But they are not exposed to the developer.

Sure they are. It's *objects* that are not exposed to the developer :) Java
doesn't let you access an object directly: A Java developer (unlike a C++
developer) can't create a local or static object, or pass an object by value
to a called method. The only thing Java lets you do with objects is access
them indirectly, via a pointer. And where a C++ object can de defined to
contain another object, all a Java object can contain is a *pointer* to
another object. Java uses the dot (".") to access fields and methods, but it
has the same meaning as C++'s arrow ("->").

Ok, I can buy that (I did a LOT of programming in C). But they are
CALLED references in Java (the NullPointerException notwithstanding).
Lets not start re-defining the nomenclature.

I once took a C++ class, and in C++ there are both pointers and
references. Confused the hell out of me. The only part of C++ that
still confuses me (no I do not program in C++).

Because you can return *ptr or &ptr, and, as I remember, depending on
the signature of the method, they have different meanings (please,
PLEASE do not start a sub-thread on this. I hope I never see C++
again.... shudder)
 
P

Patricia Shanahan

Wojtek said:
Chris Dollin wrote : ....
Object a = new Object();
Object b = a;
a = null;

b still holds a reference to the new Object. In C/C++ with pointer to pointer referencing, b would point to nothing.

Could you post what you consider to be the equivalent C or C++ code?

I would expect something like:

Object *a = new Object();
Object *b = a;
a = null;
While a reference to an object is actually a pointer (which I am NOT
arguing), you cannot manipulate that reference. Other than re-asigning
it. Whereas in C/C++ move it through an array using pointer arithmetic.

I think we need to clarify what we all agree about and what, if
anything, we disagree about. Here is my position:

1. Java does have pointers, and it impossible to work with arrays or
objects without using them.

2. Java does not have pointer arithmetic as introduced in C and
continued in C++.

3. Pointers without arithmetic existed in at least one published
language definition, the Pascal Report, when C was still being developed.

4. Some Java behavior is much easier understood and explained in terms
of pointers than by hiding them.

If you disagree with any of these statements, please indicate which. For
anyone who disagrees with #4, please provide your explanation of the
behavior of the following program:

public class CallByQuestion {
static StringBuffer x;
public static void main(String[] args) {
StringBuffer myBuf = new StringBuffer();
x = myBuf;
System.out.println("Before call:");
System.out.printf(" x==myBuf is %b%n",x==myBuf);
System.out.printf(" myBuf contents: %s%n", myBuf.toString());
myMethod(myBuf);
System.out.println("After call:");
System.out.printf(" x==myBuf is %b%n",x==myBuf);
System.out.printf(" myBuf contents: %s%n", myBuf.toString());
}

private static void myMethod(StringBuffer myBuf) {
StringBuffer y = myBuf;
myBuf = new StringBuffer("Some data");
System.out.println("Inside myMethod:");
System.out.printf(" x==myBuf is %b%n",x==myBuf);
System.out.printf(" myBuf contents: %s%n", myBuf.toString());
y.append("Some other data");
}
}

Patricia
 
M

Mike Schilling

Wojtek said:
Mike Schilling wrote :
Wojtek said:
Gordon Beaton wrote :
On Tue, 20 Mar 2007 14:00:37 GMT, Wojtek wrote:
Yes, but the use of pointers is hidden from view. If you use
pointers, then you should be able to have an array of pointers.

This is how you declare an array of pointers in Java:

Object[] array;

Which means that you should be able to do pointer arithmetic.

That isn't a logical conclusion of the preceding statement.

So while yes Java uses pointers beneath the hood, they are not
exposed to the developer.

Just because Java doesn't offer the same set of pointer operations
that say, C does, doesn't mean that Java doesn't have pointers.

Sure Java has pointers. But they are not exposed to the developer.

Sure they are. It's *objects* that are not exposed to the developer
:) Java doesn't let you access an object directly: A Java
developer (unlike a C++ developer) can't create a local or static
object, or pass an object by value to a called method. The only
thing Java lets you do with objects is access them indirectly, via a
pointer. And where a C++ object can de defined to contain another
object, all a Java object can contain is a *pointer* to another
object. Java uses the dot (".") to access fields and methods, but
it has the same meaning as C++'s arrow ("->").

Ok, I can buy that (I did a LOT of programming in C). But they are
CALLED references in Java (the NullPointerException notwithstanding).
Lets not start re-defining the nomenclature.

I suspect they're called that to distinguish them from C and C++ pointers,
to emphasize that they're not unsafe and don't support pointer arithmetic.
But that's marketing. In real life, they're pointers.
I once took a C++ class, and in C++ there are both pointers and
references. Confused the hell out of me. The only part of C++ that
still confuses me (no I do not program in C++).

Java references are a lot like C++ pointers, and have pretty much nothing in
common with C++ references. For one thing, C++ references can't be reset;
once they're "attached" to an object, they stay attached for good.
 
M

Mike Schilling

Patricia said:
I think we need to clarify what we all agree about and what, if
anything, we disagree about. Here is my position:

1. Java does have pointers, and it impossible to work with arrays or
objects without using them.

2. Java does not have pointer arithmetic as introduced in C and
continued in C++.

3. Pointers without arithmetic existed in at least one published
language definition, the Pascal Report, when C was still being
developed.
4. Some Java behavior is much easier understood and explained in terms
of pointers than by hiding them.

As usual, Patricia has ruined a perfectly good argument by making things
overly clear :)
 
J

Jussi Piitulainen

Patricia said:
I think we need to clarify what we all agree about and what, if
anything, we disagree about. Here is my position: ....
4. Some Java behavior is much easier understood and explained in
terms of pointers than by hiding them.

If you disagree with any of these statements, please indicate
which. For anyone who disagrees with #4, please provide your
explanation of the behavior of the following program:

I would just say that the variables have the same value or that they
have a different value. Usually I would shorten this even further:
when talking about the values of x and y I would just say that x and y
are different, or are the same.

Pointer talk is needed only to explain how this is implented.
public class CallByQuestion {
static StringBuffer x;
public static void main(String[] args) {
StringBuffer myBuf = new StringBuffer();
x = myBuf;

Now x and myBuf are the same object.
System.out.println("Before call:");
System.out.printf(" x==myBuf is %b%n",x==myBuf);
System.out.printf(" myBuf contents: %s%n", myBuf.toString());
myMethod(myBuf);
System.out.println("After call:");
System.out.printf(" x==myBuf is %b%n",x==myBuf);
System.out.printf(" myBuf contents: %s%n", myBuf.toString());
}

private static void myMethod(StringBuffer myBuf) {

Now myBuf and myBuf are the same object. (These are the myBuf of main
and myBuf of myMethod.)
StringBuffer y = myBuf;

Now y and myBuf are also the same object. (Either myBuf: they are the
same.)
myBuf = new StringBuffer("Some data");

No y and myBuf are the same object, and y and myBuf are different
objects, and myBuf and myBuf are different objects.

The confusing part is that there are two different variables with the
same name. Pointer talk is not less confusing: myBuf and myBuf point
to different objects; the values of myBuf and myBuf point to different
objects; the pointers that are the values of myBuf and myBuf point to
different objects; nothing helps but keeping myBuf-of-main separate
from myBuf-of-myMethod, and that is not a pointer issue.
System.out.println("Inside myMethod:");
System.out.printf(" x==myBuf is %b%n",x==myBuf);
System.out.printf(" myBuf contents: %s%n", myBuf.toString());

Since x and myBuf are different objects, there is nothing surprising
in their having a different state. (That is the myBuf of myMethod.)
y.append("Some other data");

Since y is still the same object as the myBuf, this changes the state
of myBuf. (That is the myBuf of main.)

The output of that program does not distinguish between variables, by
the way. All references to x are to the same variable while references
to myBuf are not.

I've always found this easy to understand, having got used to it in
Common Lisp and Scheme. Objects retain their identity when they are
passed around and stored in data structures.

Pointer talk explains the implementation but is not so useful (to me)
for understanding program behaviour. What matters is object identity.

Oh yes, there is another use for pointer talk: to explain this to
people who come from the other kind of languages where you do have the
choice of passing either a pointer or "the object itself", but there,
confusingly, "the object itself" does _not_ retain its identity when
it's passed or stored somewhere. A copy is made. That's when _I_ get
confused.
 
W

Wojtek

Mike Schilling wrote :
I suspect they're called that to distinguish them from C and C++ pointers, to
emphasize that they're not unsafe and don't support pointer arithmetic. But
that's marketing. In real life, they're pointers.

But pointers in C/C++ hold the actual memory location of the start of
the object.

In Java (I could be wrong here...) the reference is a location in the
JVM heap management. So that the Garbage Collector can know if there
are any references to the object. The heap management then maps the
location to an actual memory address in the heap.

If the Java reference held only the memory location, then it would be a
lot more complicated.

There is an IBM white paper (
http://www-128.ibm.com/developerworks/java/library/j-perf08273.html )
which describes short term object memory vs long term object memory.
The white paper states that the JVM should first store an object in the
short term memory. If the object's lifetime exceeds some amount, then
it is moved to long term memory.

Quote: "Modern JVMs use a generational garbage collection scheme,
creating young objects in one space (called Eden) and then moving them
to another space if they survive past the first garbage collection.
Collecting objects in Eden, the young generation space where new
objects are created, is much faster than garbage collecting objects in
the "old" generation space."

If a large number of references exist for a given object, then when
that object is moved, every reference would need to be updated. In a
multi-threaded environment, this is problematic.

However if the reference points to a heap entry, then just that entry
would need to be updated, which is much faster.
 
C

Chris Uppal

Jussi said:
Pointer talk is needed only to explain how this is implented.

I think it goes further than that.

For one thing, there is no requirement that Java's object references be
/implemented/ as classical (C/Pascal-style) "pointers" -- i.e. memory locations
containing the addresses of other memory locations. The "pointer" concept is
more general than that (even in C or Pascal), and is more about the logical
properties of a specific kind of "thing", than of bit-level implementation
details.

However the terminology ./does/ convey a strong image of an implementation, and
that picture (I think) helps a lot in understanding what's going on.

In particular, it helps explain what's going on with variables, and the things
the variables refer /to/. Without some concept that is functionally equivalent
to pointers (without arithmetic) , the distinction between reference and
referent will and must remain unclear. Note that it is by no means obvious
that a language has to work the way Java does. For instance in older versions
of PHP (as I understand it) all "things" were values -- even if compound.

I've always found this easy to understand, having got used to it in
Common Lisp and Scheme. Objects retain their identity when they are
passed around and stored in data structures.

Yes, but Lisp/Scheme have very specific notions of (a) variables, and (b) the
lack thereof. You just wouldn't hit the problem of understanding the
difference between references and values in a referentially-transparent
context.


I'm not saying that I think the way that Java works is difficult or obscure in
the slightest, but it doesn't seem to be as obvious to everyone as all that.

(As an aside, there seems to be a tradition of expecting pointers (even without
pointer arithmetic) to be somehow difficult for beginners to understand, and
some books and teachers go to enormous lengths to try to explain them. They
draw complicated pictures full of boxes and arrows. My personal suspicion is
that the /only/ reason anyone ever has any difficulty with pointers is that the
teachers confuse the Hell out of them with all the boxes and arrows....)

-- chris
 
S

Steve Wampler

Jussi said:
I would just say that the variables have the same value or that they
have a different value. Usually I would shorten this even further:
when talking about the values of x and y I would just say that x and y
are different, or are the same.

Pointer talk is needed only to explain how this is implented.

That breaks down when Java's call-by-value semantics and primitive
arguments versus object arguments. While I prefer 'reference' to 'pointer',
it greatly helps to have that general concept available when explaining
why:

f(x)

cannot alter the value of x if it's a primitive, but can alter the
'value' of x if it's an object. Note the quotes - I know it's not
altering the value of x - which is a reference to an object whose
value may change as a result of the call. f() can't change the
reference, but unless x is immutable it most likely can change
the value of the object being referenced. How does one explain this
without introducing the concept of a reference (pointer)?

The use of references in languages that don't have pointer arithmetic
has been around forever (forget Pascal, that's a newbie in this
area!).
 
S

Steve Wampler

Wojtek said:
In Java (I could be wrong here...) the reference is a location in the
JVM heap management. So that the Garbage Collector can know if there are
any references to the object. The heap management then maps the location
to an actual memory address in the heap.

Java might, but it's not a requirement. There are languages (oh, Icon
springs to mind) where the references *are* pointers directly to the heap
objects. GC works just fine there. No need for indirection just so GC works.

It wouldn't surprise me if Java did the same thing.
 
C

Chris Uppal

Wojtek said:
No it is a call by reference. If it was a call by value, then a clone
of the StringBuffer (in the following code) would be placed in the
stack. The method would then use the clone and the calling main() would
still use its private copy.

Two things.

One) It is important not to let the "call-by-XXX" terminology get confused with
other words we use which are also spelled XXX. In particular the expression
"call-by-reference" is /not/ directly connected with what we call references
(or pointers) in Java. "Call-by-reference" refers to a specific semantics of
function calls (and nothing /except/ the semantics of function calls); and --
depending on how you want to think about it -- you can see Java's function call
semantics as either call-by-reference or call-by-value. If you take a
high-level view of the function call semantics (where objects are concerned)
then you can, if you wish, think of the /object itself/ being passed by
reference (that is, however, rather sloppy [ab]use of a term with a specific
technical meaning -- see below). Alternatively, you can look at the values
involved, and see that Java doesn't (as Mike said earlier) ever let you get
hold of an object itself -- all you ever have is a reference to an object. And
references are most definitely /NOT/ passed by reference. They are always
passed by value.

Two) In most cases, when people talk about "pass by reference" they are talking
about the /variables/ involved not (as in the previous paragraph) the
/objects/. If a variable is used as the parameter to a function call, then
the most typical use of the phrase "pass by reference" is that the variable's
own contents (as distinct from the state of its referent) can be rebound by the
function call. (That's what can happen with C++'s "reference variables" for
instance). And that is /never/ true in Java -- never even remotely true.

So, taking the two points together, most Java programmers prefer to stick very
tightly to the low-level view of parameter passing and state that Java /only/
has call by value, but that some of those values are references to objects.
Anything else is known to lead to massive confusion.

In Java (as in C) the only available semantics for function calls is pass by
value. Don't talk about Java having "pass by reference" because that means
something different -- you can pass references to functions, of course, but
that /is not the same thing as pass-by-reference/.

-- chris
 
W

Wojtek

Chris Uppal wrote :
So, taking the two points together, most Java programmers prefer to stick
very tightly to the low-level view of parameter passing and state that Java
/only/ has call by value, but that some of those values are references to
objects. Anything else is known to lead to massive confusion.

Full agreement there. As I stated in the sentence following your quote
:)
 
S

Steve Wampler

Chris said:
If a variable is used as the parameter to a function call, then
the most typical use of the phrase "pass by reference" is that the variable's
own contents (as distinct from the state of its referent) can be rebound by the
function call.

As the most extreme example of pass-by-reference, consider that in FORTRAN
(1 or 2, I forget!), the following code (forgive the incorrect syntax, it's
been a while since I programmed in F2):

CALL F(2)
PRINT 2*2
END

SUBROUTINE F(I)
I = 3
END

would nicely output '9'. Such rebinding of constant values was,
uh, frowned upon.
 
M

Mike Schilling

Wojtek said:
Mike Schilling wrote :

But pointers in C/C++ hold the actual memory location of the start of the
object.

They do in the usual implementations, but there's no requirement in the
language defintions that they do.
In Java (I could be wrong here...) the reference is a location in the JVM
heap management. So that the Garbage Collector can know if there are any
references to the object. The heap management then maps the location to an
actual memory address in the heap.

It's possible to do GC when pointers are actual memory addresses. I used to
work on a system that worked that way.
 
S

Stefan Ram

Wojtek said:
But pointers in C/C++ hold the actual memory location of the
start of the object.

There is no language »C/C++«.

In C++, this will print »0«:

#include <iostream>
#include <ostream>

struct A { int a; };
struct B { int b; };
struct C : A, B { int c; };

int main()
{ C c;
A * a = &c;
B * b = &c;
::std::cout <<(( void * )a==( void * )b )<< '\n'; }
 
M

Mike Schilling

As the most extreme example of pass-by-reference, consider that in FORTRAN
(1 or 2, I forget!), the following code (forgive the incorrect syntax,
it's
been a while since I programmed in F2):

CALL F(2)
PRINT 2*2
END

SUBROUTINE F(I)
I = 3
END

would nicely output '9'. Such rebinding of constant values was,
uh, frowned upon.

An early lesson in the value of immutable objects...
 
L

Lew

Steve said:
The use of references in languages that don't have pointer arithmetic
has been around forever (forget Pascal, that's a newbie in this
area!).

FORTRAN.

-- Lew
 
L

Lew

Jussi said:
Pointer talk is needed only to explain how this is implented.
public class CallByQuestion {
static StringBuffer x;
public static void main(String[] args) {
StringBuffer myBuf = new StringBuffer();
x = myBuf;

That was Patricia's point, save for the "only", right?
The confusing part is that there are two different variables with the
same name. Pointer talk is not less confusing: myBuf and myBuf point
to different objects; the values of myBuf and myBuf point to different
objects; the pointers that are the values of myBuf and myBuf point to
different objects; nothing helps but keeping myBuf-of-main separate
from myBuf-of-myMethod, and that is not a pointer issue.

All your verbiage with the pattern "... point to ..." seems to explain things
quite clearly.

-- Lew
 
L

Lew

Wojtek said:
Chris Uppal wrote :

When I read SCJP study materials, they have always asserted unequivocally
"call-by-value" as the only correct answer to "how does Java pass method
arguments?"

-- Lew
 

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,888
Messages
2,569,964
Members
46,293
Latest member
BonnieHamb

Latest Threads

Top