Unexpected result when use swap function to swap two references in Java - java

I have two references, reference a point to object a, reference b point to object b, then I called a swap function to try to let a point to object b, b point to object a, it is swapped in the swap function, but result in main function didn't change. So what I should do?
The swap function:
private void swap(Stack<TreeNode> a, Stack<TreeNode> b) {
Stack<TreeNode> temp = new Stack<TreeNode>();
temp = a;
a = b;
b = temp;
}

The result of the swap is local to the method, it won't have any effect once the method returns to its calling point - you're simply swapping local variables. When the method got invoked, a copy of a reference to the objects got passed, not the actual objects themselves.
Java has pass-by-value semantics, in the case of objects being passed as parameters to a method that means that a copy of the reference is passed. Take a look at this post for an example.
Also notice that the object references existing before calling the method, and the references existing inside the method as parameters are actually pointing to the same object, so any modifications to the object's contents you do inside a method will remain in place once the method returns.

You're changing local parameters, not the acutal contents of those references. One solution is to modify the instances you're sending. E.g.
private boolean swap(Stack<TreeNode> a, Stack<TreeNode> b)
{
if(a == null || b == null) return false;
Stack<TreeNode> temp = new Stack<>();
while(!a.empty()) temp.add(a.pop());
while(!b.empty()) a.add(0, b.pop());
while(!temp.empty()) b.add(temp.pop());
return true;
}

Related

Why do they call it pass by value in Java? [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
Ok, so I am a relatively new programmer. I have read over and over about passing variables. From what I have read here is what I've come to understand: In Java, when you pass a variable to a method (be it primitive or Object) you are ALWAYS passing by value. But what you are REALLY doing is passing a copy of the reference to an object or variable in memory.
So why do they call it pass by value? It seems to me you are passing by reference. Also, in C when you pass a pointer to a function, aren't you passing the address of a variable in memory? Yet it is called pass by value. What am I overlooking? Can someone please explain and clarify why I this? I know how to pass variables and such and I have read several SO posts on this but I am not fully satisfied yet. Consider an example:
static void setNameStatic(Dog d, String name) {
d.name = name;
}
public static void main (String args[]) {
Dog d = new Dog("dog1");
System.out.println( d.getName() );
setNameStatic( d, "dog2" );
System.out.println( d.getName() );
}
Won't this output: dog1 and dog2. So aren't you going to where the reference is referring to and changing data around? What exactly does the value have to do with here? Any helpful comments are appreciated. And yes, I know it is pass by value, but why isn't it called "pass by sending copy of reference" lol?
Update: Thanks to everyone that gave a helpful answer. I know this was marked duplicate, and sorry about that. I am satisfied with the answers now.
Your memory looks like this at the moment of:
Dog d = new Dog("dog1");
Stack (with local vars) Heap
+-----------+ points to
| Dog d | ---------------> real dog object
+-----------+
| ... |
+-----------+
| ... |
+-----------+
And then, when you pass in a reference to a method, it looks something like this (where the Dog dog2 is the method argument):
Stack (with local vars) Heap
+-----------+
| Dog d | ---------------> real dog object
+-----------+ ^
| ... | |
+-----------+ |
| Dog d2 |------------------------------
+-----------+
So, the reference is passed by value. It points to the same object but it is the new reference!
Meaning, if you would try something like this:
public static void main(String ... args) {
Dog d= new Dog("dog1");
setNameStatic(d, "dog2");
System.out.println(d); // Still prints dog1 !!!
}
static void setNameStatic(Dog d2, String name) {
d2= new Dog(name);
}
Because the new (copied) reference now points to the new object on heap and the original object has not changed.
Because the value of any variable of reference type is its address in memory.
Because the value of any variable of primitive type is its value itself.
So you always pass values of variables.
Every variable is passed by value. In the instance of primatives, we have the naive case - the values are passed into the function.
In the instance of Objects, we have a slightly more complicated although analogous paradigm - the references to the objects are passed by value.
Note the subtle differences:
//This is essentially a no-op. The values are only local to the function
void swap(int a, int b){
int temp = a;
a = b;
b = temp;
}
//This is different. The references to a and b are passed by value so the values of a.x and b.x are actually swapped on return.
void swap(Point a, Point b){
int temp = a.x;
a.x = b.x;
b.x = temp;
}
Passing by value means that the value is transferred to method, i.e. yet another copy of the same value is created:
int i = 5; // one copy of 5
foo(i);
private void foo(int n) {
// here n is 5, however it is "another" 5
}
The evidence of passing by value is that you cannot change your i from within the method foo():
int i = 5; // one copy of 5
foo(i);
// i is still 5 here
private void foo(int n) {
n = 6;
// n is 6, however it is actual inside the method only.
}
The same is with objects, however in that case reference is passed by value.
Also, in C when you pass a pointer to a function, aren't you passing the address of a variable in memory? Yet it is called pass by value.
No it is not. When you pass a pointer to a value to a function in C, it is known as 'pass by reference'. The function can directly access & modify the original value because it has it's address. Pass by value is when you pass the value of objects instead of their locations or addresses. Look at the following examples.
int addOne(int x)
{
return x + 1;
}
void destructiveAddOne(int *x)
{
*x += 1;
}
int main(void)
{
int x = 5;
int y = 5;
// We pass the _value_ of x, ie, 5 to addOne, and store the result in z.
// The value of x will remain unchanged, ie, 5.
int z = addOne(x);
// We pass a REFERENCE to y, ie, it's address to destructiveAddOne()
// destructiveAddOne then modifies the value of y to be y + 1. The value of y
// has now CHANGED to 6. This is call by reference.
destructiveAddOne(&y);
return 0;
}
A variable holds the bits that tell the JVM how to get to the referenced Object in memory (Heap).
When passing arguments to a method you ARE NOT passing the reference variable, but a copy of the bits in the reference variable. Something like this: 3bad086a. 3bad086a represents a way to get to the passed object.
So you're just passing 3bad086a that it's the value of the reference.
You're passing the value of the reference and not the reference itself (and not the object).
This value is actually COPIED and given to the method.
Had that before:
Is Java "pass-by-reference" or "pass-by-value"?
It is a tricky thing to get your head round. I think of it as real numbers, albeit abstracted. Say your first dog, dog1, is created at memory location "100,000" (I know but bear with me). You pass the reference's value of 100,000 around to methods. Your method changes the name of the object living at 100,000.
If you pass your dog1 object into a method that does d = new Dog("dogXXX"), then it will work with a brand new object at (say) 200,000 leaving your dog1 at memory address 100,000 unchanged.
Apologies for the memory address abuse which will have experts spitting their coffee...
In java you're passing parameters by value to the methods, but the parameters are themselves ref type if the parameter is an object.
As a contrast in a programming language like C that passing by reference is allowed, if you print a reference you get something different from what you get when print it's value.
To insure that objects are reference types and compare them with primitives, Try this:
public class TestClass {
public static void main(String[] args) {
String s = new String("a");
String t = new String("a");
System.out.println(s==t);
char a = 'a';
char b = 'a';
System.out.println(a==b);
}
}
The result is :falsetrue
References in Java are passed by value of the reference.
When you pass reference as a method parameter copy is created and you operate on this copy.
To illustrate it have a look at this sample code:
final Person person = new Person();
person.setName("A");
changeName(person, "B");
System.out.println(person.getName());
Now if we have changeName implemented as this:
private static void changeName(Person person, String name) {
person.setName(name);
}
Then the result is B. It's because copy of the reference still points to the same object and there is possibility to modify it.
On the other hand if you change the changeName method to this:
private static void changeName(Person person, String name) {
person = new Person();
person.setName(name);
}
Then the result is A. It's because copy of the reference points to the new object, but original reference still points to the original object and it's value is not modified.
If Java would pass object references by reference than the result would be B, because it would operate on the original object.
When you pass an object as a parameter in Java, you actually pass a reference, and the reference is the value used in the stack. However, any assignment you make to this reference inside the method will not be observed by the caller, because you only change a copy of the reference. Same goes with primitive values as parameters.
In other languages (like C++), you have the option to pass by reference, allowing you to change the reference itself from within a method. In Java, for example, you can't implement a swap method that takes two parameters and swaps them. In C++ it's possible.

Clone method for Java arrays

What exactly does the clone() method in Java return when used on an array?
Does it return a new array with data copied from the original?
Ex:
int[] a = {1,2,3};
int[] b = a.clone();
When the clone method is invoked upon an array, it returns a reference to a new array which contains (or references) the same elements as the source array.
So in your example, int[] a is a separate object instance created on the heap and int[] b is a separate object instance created on the heap. (Remember all arrays are objects).
int[] a = {1,2,3};
int[] b = a.clone();
System.out.println(a == b ? "Same Instance":"Different Instance");
//Outputs different instance
If were to modify int[] b the changes would not be reflected on int[] a since the two are separate object instances.
b[0] = 5;
System.out.println(a[0]);
System.out.println(b[0]);
//Outputs: 1
// 5
This becomes slightly more complicated when the source array contains objects. The clone method will return a reference to a new array, which references the same objects as the source array.
So if we have the class Dog...
class Dog{
private String name;
public Dog(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and I create and populate an array of type Dog...
Dog[] myDogs = new Dog[4];
myDogs[0] = new Dog("Wolf");
myDogs[1] = new Dog("Pepper");
myDogs[2] = new Dog("Bullet");
myDogs[3] = new Dog("Sadie");
then clone dog...
Dog[] myDogsClone = myDogs.clone();
the arrays refer to the same elements...
System.out.println(myDogs[0] == myDogsClone[0] ? "Same":"Different");
System.out.println(myDogs[1] == myDogsClone[1] ? "Same":"Different");
System.out.println(myDogs[2] == myDogsClone[2] ? "Same":"Different");
System.out.println(myDogs[3] == myDogsClone[3] ? "Same":"Different");
//Outputs Same (4 Times)
This means if we modify an object accessed through the cloned array, the changes will be reflected when we access the same object in the source array, since they point to the same reference.
myDogsClone[0].setName("Ruff");
System.out.println(myDogs[0].getName());
//Outputs Ruff
However, changes to the array itself will only affect that array.
myDogsClone[1] = new Dog("Spot");
System.out.println(myDogsClone[1].getName());
System.out.println(myDogs[1].getName());
//Outputs Spot
// Pepper
If you generally understand how object references work, it is easy to understand how arrays of objects are impacted by cloning and modifications. To gain further insight into references and primitives I would suggest reading this excellent article.
Gist of Source Code
clone() method creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object. The general intent is that, for any object x, the expression:
x.clone() != x
Will be true, and that the expression:
x.clone().getClass() == x.getClass()
Will be true, but these are not absolute requirements.
While it is typically the case that:
x.clone().equals(x)
will be true, this is not an absolute requirement.
By convention, the returned object should be obtained by calling super.clone. If a class and all of its superclasses (except Object) obey this convention, it will be the case that x.clone().getClass() == x.getClass().

Java Heap and Pass By Value

I am a little confused as to how my Java program is allocating memory. Below is a typical situation in my program. I have an object created on the Heap inside of a class which I pass to other functions inside of other classes.
public class A {
private List<Integer> list = new ArrayList<Integer>();
public A() {
for(int i = 0; i < 100; i++)
list.add(i);
}
public void foo() {
B b = new B();
b.bar(this.list);
}
}
public class B {
A a = new A();
public int bar(List<Integer> list) {
list.add(-1);
return list.size();
}
public int getSize() {
List<Integer> list = a.list;
return a.size();
}
}
My question(s) are about how the memory is used. When A's list gets passed to B.bar(), does the memory get copied? Java is pass-by-value so I assumed the B.bar() function now contains a copy of the list which is also allocated on the heap? Or does it duplicate the list and put it on the stack? Or is the list duplicated at all? Similarly what applies to these memory questions inside of B.getSize()?
It's probably clearer to say that in Java, object references are passed by value.
So B gets a copy of the reference (which is a value) to the List, but not a copy of the List itself.
You can easily prove this to yourself by getting B to modify the List (by adding or removing something), and observing that A's List also changes (i.e. it is the same List).
However, if you change B's reference to the List (by creating and assigning a new List to it), A's reference is unchanged.
Java is pass-by-value, but the value of an expression or variable is always either a primitive or a reference. A reference, in turn, is either null or a pointer to some object.
In your case: private List<Integer> list = new ArrayList<Integer>(); declares list as having a reference type, and makes its value a pointer to a newly allocated ArrayList object.
When you use list as an actual argument, for example on the b.bar(this.list); call, the formal argument list in b.bar is initialized with a copy of that pointer. That is, bar's formal argument points to the same ArrayList object as A created. The ArrayList object is not copied.
Java is pass-by-value, dammit!
However, you only ever have access to references to Objects. In that sense, you are passing Object references by value.

How to verify call by value of Java?

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 !

Is there any performance difference between StringBuilder.append and assigning value to StringBuilder in java

I have a StringBuilder a. I have to append a's content to StringBuilder b. If b is null, then assign b=a, otherwise b.append(a.toString()).
Is there any performance difference on checking if the StringBuilder is null or not?
method_a(StringBuilder a, StringBuilder b) {
if (b != null) {
b.append(a.toString();
} else {
b=a;
}
}
b = a; will have higher performance, since it's just assigning a reference. b.append is a method call, and requires copying characters, and (potentially) creating a new character array.
The question is whether that's what you want. Note that a and b are both local variables, so if you do b = a, you can use b until the end of the method. However, it will not affect the caller.
In contrast, b.append modifies the object in-place. No new object is created, so this mutation is visible outside the method.

Categories

Resources