I'm working on an assignment right now, and am confused by this. The code given is simple:
public class Variables{
public static void main(String[ ] args){
StringBuffer b = "ghi";
f(b);
System.out.println(b):
}
public static void f(StringBuffer p){
p.concat("jkl");
}
}
The question simply asks what the output of the print statement will be. My first thought was simply "ghi", but this was incorrect. If the method f is taking b as a parameter and setting it to p, then how does .concat() modify b? I've read through the StringBuffer documentation and dont understand why this wouldn't end up with b equaling "ghi" while p is "ghijkl".
Basically, how is the .concat() method called on p also modifying b?
First, you need to create a StringBuffer correctly.
StringBuffer foo = new StringBuffer("some string");
You passed an object to a function. Java passes objects as references (the references themselves of course are passed by value). See: Is Java "pass-by-reference" or "pass-by-value"?
Since you have a reference to a StringBuffer and not a copy of it, you are actually modifying the same object as you would as if you were in main.
This is the difference between parsing by reference and parsing by value.
When you create a method taking a primitive, for example, it undergoes what is called parsing by value. The JVM pretty much creates a copy of the value and that is what you get in the method.
int j = 0;
foo(k);
System.out.println(j); //Will still be 0.
public static void foo(int i) {
//i is not j (what you called the method with), it is a copy of it that is only valid within this method
i++;
}
Now when you call the method with an object such as a StringBuffer you are parsing by reference. This means that you are not parsing the value of the StringBuffer(not parsing a StringBuffer` with "ghi" as its contents), but you are rather parsing a pointer to it. Using this pointer you can still operate on the original object within other methods and bodies of code.
Related
I was going through this excellent article on Java reference semantics by Jon Skeet, where he states that
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;
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 g.
my understanding could be wrong. the program below does change the Stringbuffer passed to the method
public class MutabilityStringBuffer {
public static void main(String[] args){
StringBuffer sb = new StringBuffer("hello");
System.out.println("String before append: "+ sb.toString());
addString(sb);
System.out.println("Sting after append "+ sb.toString());
String s = "hello";
System.out.println("String before append: "+ s);
addString(s);
System.out.println("Sting after append "+ s);
}
public static void addString(StringBuffer word){
word.append(" world!");
}
public static void addString(String word){
word+=" world!";
}
}
ofcourse, Jon Skeet could not be wrong. But I see that the Stringbuffer can be changed by passing it to method, because stringbuffer is mutable, which is a bit contradictory to what Skeet posted. please clear my understanding here.
Thanks
See comments
StringBuffer sb = new StringBuffer("hello"); // sb holds reference
System.out.println("String before append: "+ sb.toString()); // you print the value
addString(sb); // you use the reference to append to the StringBuffer
System.out.println("Sting after append "+ sb.toString()); // you print the value
String s = "hello"; // s holds a refernece
System.out.println("String before append: "+ s); // you print its value
addString(s); // // the word variable would hold a new reference inside the method
System.out.println("Sting after append "+ s); // you print its value
In here
public static void addString(String word){
word+=" world!";
}
The original value of the reference passed to word changes when you reassign it with
word+=" world!";
It goes something like this
String word = [copy of value of the argument's reference];
word = word.toString() /* toString() is unnecessary, but just to make the point */ + " world";
where the result of String concatenation is a new String object and therefore a new reference.
In the following
public static void addString(StringBuffer word){
word.append(" world!");
}
you access the object referenced by word, call a method on that object which internally modifies a char[]. So you've changed the value of the object, not the value of the reference. Changing the reference would look like
public static void addString(StringBuffer word){
word = new StringBuffer("Answer to the Ultimate Question of Life, the Universe, and Everything: ");
word.append("42");
}
The append is performed on a new StringBuffer object, not the one you passed as an argument, proof that the objects are passed by value.
This has been discussed to death. Anyway, given some idle time, here is my response. It is the same response I always give, and it links to the same wikipedia article on evaluation strategies I always link to.
I find that using the term Call by (Object) Sharing removes most ambiguities when describing the semantic behavior of passing objects as arguments in Java (and many other languages including Python, C#, etc). Doing so clearly identifies any [im]mutability considerations. That is, the object accessed inside the method is the same object as outside! No new object has been created, copied, cloned or otherwise duplicated during this calling/evaluation strategy - so any mutable change made the object affects the same "shared" object.
Passing the reference-of an object an object using Call by Value is an implementation detail, albeit one that is discussed in depth in the Java Language Specification (JLS). In the case of Java it would be more "accurate" to say Call by Value of the Reference-to the Object - but this is still implemented-as Call by Value. (Some languages like ECMAScript, however, achieve the exact same Call by Sharing semantics without discussing any such implementation details.)
To avoid confusion, I use Call by Reference only to mean that the called function can modify variable bindings (which are orthogonal to object mutability) of the caller through re-assignment to parameters. Unfortunately Call by Reference has been given alternative - and confusing - meanings in some language circles.
I have question about one method of InputStream class, because it doesn't seem to me it could ever work.
Let we have something like this:
InputStream is;
byte[] b = new byte[64];
is.read(b);
// and now the byte array b contains data comming through InputStream???
I would understand if usage of the .read() method would look something like this:
b = is.read();
Because the read method would be returning byte array.
But how can the real method write something to its argument and make it visible outside of itself?
It's like I would have this:
String myString = "myText";
public void myMethod(String s) {
s = "abc123";
}
myMethod(myString);
// and now is the content of myString equal to "abc123" instead of "myText" ???
// ANSWER: no!
Thanks for your replies.
Everything except primitives types are objects in java(including array). The objects are passed by copy of reference from one method to another. So if the called method makes changes to the object passed to it, method is eventually making changes to the same object which was passed to it. Hence, changes are reflected to the calling method as well.
You need to learn about objects and how are they passed between method calls to understand this in detail. Please refer this link for better understanding.
Because the read method would be returning byte array.
Eh? Where did you read that? InputStream's .read() method returns an integer.
how can the real method write something to its argument and make it visible outside of itself?
Because you pass in a reference to an array where the .read(byte[]) will write. And the return value of this method is the number of bytes actually written to the byte array passed as an argument.
This code works:
public void writeOneToFirstElement(final int[] array)
{
array[0] = 1;
}
final int[] foo = { 0 };
writeOneToFirstElement(foo);
System.out.println(foo[0]); // prints 1
THe Array is just a reference to the object and cause the adress where the data resides doesnt change on modifications it can work that way
Explained here:
http://www.javaworld.com/javaqa/2000-05/03-qa-0526-pass.html
Edit: Typo
byte array as well as String are reference types..When you pass them as argument there reference are copied and they all refer to the same object..
For example, a remote is like a reference to a TV.When you pass the remote to another person,he's still able to access the TV
The objects are passed by copy of reference from one method to another. So if the called method makes changes to the object passed to it, method is eventually making changes to the same object which was passed to it. Hence, changes are reflected to the calling method as well. For example replace the String in the parameter with String[] and check the output.
public static void main(String[] args)
{
String[] myString = {"myText"};
myMethod(myString);
System.out.println(myString[0]);
}
public void myMethod(String[] s) {
s[0] = "abc123";
}
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 9 years ago.
public class StackOverFlow {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();
al.add("A");
al.add("B");
markAsNull(al);
System.out.println("ArrayList elements are "+al);
String str = "Hello";
markStringAsNull(str);
System.out.println("str "+ str);
}
private static void markAsNull(ArrayList<String> str){
str.add("C");
str= null;
}
private static void markStringAsNull(String str){
str = str + "Append me";
str = null;
}
}
This outputs:
ArrayList elements are [A, B, C]
str Hello
In the case of ArrayList, the added elements are getting retrieved.
In case of String the method call has no effect on the String being passed. What exactly is the JVM doing? Can anyone explain in detail?
In the case of Arraylist string objects the added elements are getting retrived. In case of String the method call has no effect on the String being passed.
It happens cause Java is Pass-by-Value and Strings are immutable
When you call
markAsNull(ArrayList<String> str)
The a new reference by name str is created for the same ArrayList pointed by al. When you add an element on str it gets added to same object. Later you put str to null but the object has the new values added and is pointed by a1.
When you call
markStringAsNull(String str)
{
str = str + "Append me";
// ...
}
The line str = str + "Append me"; creates a new String object by appending the given string and assignes it to str. but again it is just reference to actual string which now pointing to newly created string. (due to immutablity) and the original string is not changed.
The markXAsNull methods are setting the local references to be null. This has no effect on the actual value stored at that location. The main method still has its own references to the values, and can call println using those.
Also, when doing the string concatenation, toString() is being called on the Object, and that is why the ArrayList is outputted as a list of its values in brackets.
From the Book: SCJP - Sun Certified Programmer for Java 6 Study Guide (Katty Sierra - Bert Bates) Chapter 3 Objective 7.3 - Passing Variables Into Methods
Java is actually pass-by-value for all variables running within a single
VM. Pass-by-value means pass-by-variable-value. And that means, pass-by-copy-ofthe-
variable!
The bottom line on pass-by-value: the called method can't change the caller's
variable, although for object reference variables, the called method can change the
object the variable referred to. What's the difference between changing the variable
and changing the object? For object references, it means the called method can't
reassign the caller's original reference variable and make it refer to a different object,
or null. For example, in the following code fragment,
void bar() {
Foo f = new Foo();
doStuff(f);
}
void doStuff(Foo g) {
g.setName("Boo");
g = new Foo();
}
reassigning g does not reassign f! At the end of the bar() method, two Foo objects
have been created, one referenced by the local variable f and one referenced by
the local (argument) variable g. Because the doStuff() method has a copy of the
reference variable, it has a way to get to the original Foo object, for instance to call
the setName() method. But, the doStuff() method does not have a way to get to
the f reference variable. So doStuff() can change values within the object f refers
to, but doStuff() can't change the actual contents (bit pattern) of f. In other
words, doStuff() can change the state of the object that f refers to, but it can't
make f refer to a different object!
Java follows passby value concept ( there is no pass by reference in java ) . So when you pass a string to the function it sends a "copy of reference" to that string to the function. So even if you set the variable to null in the function, when it returns to the caller it refers its original value only. That's why original string has no effect.
In case of Arraylist, copy of reference refers to the original Arraylist (which is also the same in case of string). But when you add something into ArrayList, it refers to the original object and so that you can see the effect. ( try in method arraylist=new ArrayList(), your original arraylist will remain as it is).
In case of string, when you do
str=str + "abc";
Java creates a new String object which will have reference to string "xyzabc" ( e.g. str="xyz") and "xyz" will be eligible for the garbage collection. But as "xyz" is still having an variable which refers to it it ( original string) will not be garbage collected. But as soon as the function call gets over "xyzabc" goes for garbage collection.
Summary of the discussion is, as long as an reference refers to the same object you can make changes in the function, but when you try to change the reference ( str=str+"abc") you are refering to the new object in the method so that your original object will remain as it is.
In Java, you may create one object, and referenced by multiple pointers. Calling a mutator method on any pointer will effectively modify the sole object, thus updating all other references.
But if you call variable assignment statements on a reference, only that pointer will be changed, since it doesn't do any object side work (this is the best I could explain...).
Passing an object to a parameter will effectively copy the reference, resulting in a single object, with two pointers - one global, and the other local.
One more point, since String is immutable, you'll actually get a new object, that is distinct from the original (from the fact that you have to say a = a + "a"), that's why it won't modify the original string.
This question already has answers here:
Changing array in method changes array outside [duplicate]
(2 answers)
Closed 3 years ago.
public class Test {
public static void main(String[] args) {
int[] arr = new int[5];
arr[0] = 1;
method(arr);
System.out.println(arr[0]);
}
private static void method(int[] array)
{
array[0] = 2;
}
}
After invoking method, arr[0] becomes 2. Why is that!?
You can call set methods on objects passed to a method. Java is pass by value, which means that you can't replace an object in a method, though you can call set methods on an object.
If Java were pass by reference, this would pass:
public class Test {
public static void main(String[] args) {
Test test = new Test();
int j = 0;
test.setToOne(j);
assert j == 1;
}
public void setToOne(int i) {
i = 1;
}
}
Java is Pass-by-Value, Dammit! http://javadude.com/articles/passbyvalue.htm
This is because Java uses Call by Object-Sharing* (for non-primitive types) when passing arguments to method.
When you pass an object -- including arrays -- you pass the object itself. A copy is not created.
If you mutate the object in one place, such as in the called method, you mutate the object everywhere! (Because an object is itself :-)
Here is the code above, annotated:
public static void main(String[] args)
{
int[] arr = new int[5]; // create an array object. let's call it JIM.
// arr evaluates to the object JIM, so sets JIM[0] = 1
arr[0] = 1;
System.out.println(arr[0]); // 1
method(arr); // fixed typo :-)
// arr still evalutes to JIM
// so this will print 2, as we "mutated" JIM in method called above
System.out.println(arr[0]); // 2
}
private static void method(int[] array)
{
// array evaluates to the object JIM, so sets JIM[0] = 2
// it is the same JIM object
array[0] = 2;
}
Happy coding.
*Primitive values always have call-by-value semantics -- that is, a copy is effectively created. Since all primitive values are immutable this does not create a conflict.
Also, as Brian Roach points out, the JVM only implements call-by-value internally: the call-by-object-sharing semantics discussed above are implemented by passing the value of the reference for a given object. As noted in the linked wikipedia article, the specific terms used to describe this behavior differ by programming community.
Additional:
Pass by value or Pass by reference in Java? -- see aioobes answer and how it relates with Brian Roachs comments. And aioobe again: Does array changes in method?
Make copy of array Java -- note this only creates a "shallow" copy.
Because that's exactly what you're telling it to do. Java passes first by value, then by reference. You're passing in the array, but any modifications you make to that array will be reflected on any other accesses to that array.
A quick example for thought:
If within method you did array = null, no change would be visible from main - as you would be changing the local value of array without modifying anything on the reference.
Because when you are passing argument like int/double/char etc. they are the primitive data types and they are call by value - meaning their values are copied to a local variable in this method (that has the same name as the names in your argument) and changes made to them are only changes made to these local var -> does not affect your primitive type variables outside the method
however an array or any object data type is called by reference -> the argument pass their address(reference) to method. that way, you still have a local variable named by them which has the reference. You can change it to reference another array or anything. but when it is referencing an array, you can use it to set the value of the array. what it does is accessing the address it is referencing and change the content of the referenced place
method(arr[0]);
I think that's supposed to be
method(arr);
But anyway the value passed as argument to the method is the reference to the array and the local variable arr in the method is referencing the same array. So, within the method you are making changes to the same array.
Java is pass by value. What confuses people is that the 'value' of a variable that refers to an object allocated on the heap is a reference, so when you pass that, you pass the reference 'by value' and therefore it refers to the same object on the heap. Which means it doesn't matter from where you modify the referent; you're modifying the same thing.
I read that Java does everything by call by value. I was wondering how to verify this fact? As far as I understand, in case of objects(not primitives) functions get its own copy of reference but points to same object. In that case, reference of that object in callee function and caller function should be different? How can I verify that? In other words, how to print the reference of the object.
System.out.println(object); //does this print reference i.e text following #
EDIT:
I understand that modifying object in callee function does change the value in caller function. I am interested in how to print the references of objects as in what property can I print on console that clearly shows me 2 different reference.
Java passes references by value. This means you'll get a copy of the reference, so once you dereference that you'll get to the same object in the heap as with the original reference.
But if Java was pass by reference:
public static void nullify(Object obj) {
obj = null;
}
public static void main(...) {
String x = "Hello";
nullify(x);
System.out.println(x);
}
The call to S.o.p. would print null if Java was pass by reference. But it isn't, so x is unchanged and you'll get Hello.
Assuming Class A property aa
A a= new A();
a.aa = 1;
// print a.aa here should be 1
method(a);
// here a.aa should be 2
Void method(A a) {
a.aa =2;
a = new A();
a.aa = 3;
}
So this shows reference was passed as value. When you change the object in the method it does not change the reference of caller.
I think the String Object#1ed3af is composed of the class name of your object and it's hashcode, separated by a #. This is a unique string, identifying it.
Read this topic to get a full explanation !