How are these two situation different? [duplicate] - java

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
public void otherMethod(){
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("abc");
list.add("abc");
someOtherMethod(list);
System.out.println(list.size());
}
public void someOtherMethod(List<String> list){
list.add("abc");
}
Invoking otherMethod prints 4.
where as
public void otherMethod(){
int a = 10
someOtherMethod(a);
System.out.println(a);
}
public void someOtherMethod(int a){
a = 11;
}
prints 10;
How are the two different. Aren't both local variables? Does sending list reference work in a different way? Please help me understand how the two scenario differ?
Before downvoting please make me understand why this below one also prints 10?
public void otherMethod(){
Long a = new Long(10);
someOtherMethod(a);
System.out.println(a);
}
public void someOtherMethod(Long a){
a = 11;
//or a= new Long(11);
}

In fact conceptually they are not different, in both cases a copy of the original value is passed in as an argument to the method. The thing is that in the first case you have a complex/composite structure of some sort so you pass in a reference copy which is different from the original reference but which still points to the original structure/object.
In the second case you pass in a copy of an int and so the method just operates on the copied int. Unlike that in the first case the method operates directly on the original structure through that copy of the reference (which it receiver from the caller).
Now, in the case of Integer and Long, you work on the original objects through a copied reference. The thing is that you cannot do much on the original object as these classes are immutable e.g. they don't have methods Integer.increment(int n) or Long.increment(long n) which change the original objects by incrementing their values. It would be same if we talk about String (which is immutable) but not the same if we talk about StringBuilder (as the latter is mutable).
public void someOtherMethod(Long a){
a = 11;
//or a= new Long(11);
}
In this example you direct the copied reference to a new object (11)
but the caller still has the original reference which still points
to the same old object (10). You have no way of changing the original
object (from within the called method) just because Long is immutable.
If it wasn't, you would be able e.g. to increment it e.g. by calling
a.increment(1). If that was possible, this is different: you're not
directing the copied reference to a new object, you're using it to call
a method on the original object.
Remember, Java is pass-by-value (always) but certain
differences like these make people confused sometimes.

int are not Objects in Java, so no a is not a reference.

Related

Java: Modifying Objects by Method Call [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 4 years ago.
I've read a gazillion times that in Java, arguments passed to methods cannot be modified by the methods. Nonetheless, I find I can modify objects I create as opposed to Java Objects. Consider the following code:
// My Integer Object
class MyInteger {
Integer val;
}
// Change Java Object
public void test1() {
Integer intval; // Integer object
intval = 123;
setInteger( intval ); // THIS DOESN'T WORK
TTY.putR( "Integer Object="+intval);
}
// Change My Object
public void test2() {
MyInteger myInt; // MyInteger object
myInt = new MyInteger();
myInt.val = 456;
setMyInteger( myInt ); // THIS WORKS!
TTY.putR( "MyIntegerObject=" + myInt.val );
}
// Set an Integer object
public void setInteger( Integer val) {
val = 888;
}
// Set a MyInteger object
public void setMyInteger( MyInteger myint) {
myint.val = 999;
}
test1 doesn't work as I have been warned. But test2 works just fine. AFAIK, both are objects and are passed by reference. So how come one works and the other doesn't? (Note: TTY is my print function)
You have either read things that were wrong, or misunderstood what you've been told.
If you pass 'a' to a java method, you cannot have the method change 'a' to be something other than 'a'. However, you can modify 'a'.
In other words, you cannot create an object of the same class as 'a' and return that in place of 'a'. The only way you can return an object created by the method is either to have a place to put a reference to that new object within an object passed to the method, or to return it as the return value from the method.
The best way I've seen this explained:
You pass an object A pointing to a memory address P.
A ===> P
When you modify A by doing A.foo = bar, A is still pointing to P, so the object at P has its property foo changed. However, let's say you want to completely reassign A, and so do A = new MyCoolObject(). This means
P_New <=== A ==/=> P
So when you modify A by doing A.foo = bar, A is no longer pointing to P, so the object at P_New has its property foo changed, but the object at P remains unchanged. This means when you exit the method and go back to whatever parent called the method, A will be completely unchanged.
Disclaimer: I saw this on another Stack Overflow article probably 5 years ago, and am too lazy to find it. If you're reading this right now and you're the person who wrote this, thanks, and forgive my casual plagiarism.
I think you are confused by pass-by-reference vs. pass-by-value. Read this to help clear it up.
You might also have misinterpreted what you've read. A mutable Object can be mutated anywhere -- where it is created or by a method it is passed to.
Good luck.
Because MyInteger the val is a public variable. So ANYONE can modify it.
// Change MyInteger object
public void setMyInteger( MyInteger val) {
val.val = 999; // ACCESING TO A PUBLIC VAR and SETTING IT
}
// Change an Integer object
public void setInteger( Integer val) {
val = 888; // Accesing to the value of the Variable and not modifing it
}
Java is a pass by value language. When you invoke any method with argument it creates new variable and you are changing this variable.
You can look at this also,
Is Java "pass-by-reference" or "pass-by-value"?

Java pass by value query [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 6 years ago.
Since java is pass by value.In below code we are passing a value to appendStringMethod not a reference, then why in main method we get HelloWorld not just Hello after calling appendStringMethod() in main.
public class test {
public static void main(String args[]) {
StringBuilder str = new StringBuilder("Hello");
appendStringMethod(str);
System.out.println(str);
}
static void appendStringMethod(StringBuilder s) {
s.append("World");
}
}
However in below code, values are not swapped.
public class Mock {
public static void main(String args[]) {
StringBuilder str1 = new StringBuilder("Hello");
StringBuilder str2 = new StringBuilder("World");
swap(str1, str2);
System.out.println(str1);
System.out.println(str2);
}
static void swap(StringBuilder s1, StringBuilder s2) {
StringBuilder s= s1;
s1=s2;
s2=s1;
}
}
It's because the reference to the StringBuilder is passed by value. You can add characters and they will be in the instance after the method returns. This in the end acts like a pass by reference. It works similarly with the Collection classes (List, Map,...), as well as your own classes.
In the case of primitive types (int,...), Java behaviour is simple: The value is copied in another instance of the primitive type.
In case of Objects, this is the same: Object variables are pointers that holds the Object’s address so the references are copied. The only exception I can think of are String Objects as the characters are stored in an array declared final so that it cannot be modified.
While Java is technically pass by value for everything, as spoken about here, It's best not to think of it like that.
When passing an instance of a class into a method, you're really passing the reference of the object by value.
StringBuilder str = new StringBuilder("Hello");
appendStringMethod(str);
In this code, you are passing a reference to the StringBuilder instance into the appendStringMethod by value.
As a result, str will become "HelloWorld" once the method has been called.
Note: This doesn't apply to primitives such as int and char. Since they are not actual objects, they won't have a reference. This means they will be passed by value in the "expected" way.
In java we pass by value of reference. Have a look at a following example:
public void foo(Integer i) {
i = new Integer(1000);
}
public void bar(Integer i) {
i++;
}
Integer n = new Integer(2000);
foo(n);
bar(n);
System.out.println(n.toString());
I believe that much of the confusion on this issue has to do with the
fact that different people have different definitions of the term
"reference". People coming from a C++ background assume that
"reference" must mean what it meant in C++, people from a C background
assume "reference" must be the same as "pointer" in their language,
and so on. Whether it's correct to say that Java passes by reference
really depends on what's meant by "reference".
--first comment

Why am I able to modify a List in a method that's out of scope, without returning it? [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 6 years ago.
Let's say I initialise my list like so:
public static void main(String[] args) {
ArrayList<String> a = new ArrayList<String>();
a.add("one");
a.add("two");
a.add("three");
a.add("four");
modifyList(a);
}
where modifyList simply changes every value to "one" like so:
private static void modifyList(ArrayList<String> a) {
for (int i = 0; i < a.size(); i++) {
a.set(i, "one");
}
}
If I print the list before and after I call this method, I expect the same original list to appear twice. But for some reason, the ArrayList that gets modified in modifyList is the same as the ArrayList in main.
If I try the same experiment with ints and Strings instead of Lists they do not get modified.
Can anyone explain why?
In Java, parameters are passed by value.
However, you passed a reference to your ArrayList to the method (and the reference itself is passed by value), and therefore the method modified the original list.
If you want to ensure that this cannot happen, you need to pass an immutable list as the parameter.

Java: Array expanding is not changing the original array? [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
I have a problem where I'm supposed to expand an array, each time creating an array with identical results. Before you tell me to just use ArrayList or something else already in the Java API, I was specifically instructed to use my own code. I tried simply creating an array that is one slot larger than my current array, though that does not seem to work very well. Here is what I have that the current moment:
public static void expand(Object[] objArray) {
Object[] objArray2 = new Object[a.length + 1];
for (int i = 0; i < a.length; i++)
objArray[i] = objArray[i];
objArray = objArray2;
}
You can't update the caller's reference inside the function. Instead, you need to return your new Object[] and update in the caller. Also, you could use System.arraycopy()
public static Object[] expand(Object[] a) {
Object[] b = new Object[a.length + 1];
System.arraycopy(a, 0, b, 0, a.length);
return b;
}
I Java, arrays are objects and objects are passed by value to methods, and that is, if you change what the reference is pointing to in the method, your changes will stay locally. The solution is to return the modified object
public static Object[] expand(Object[] objArray) {
Object[] objArray2 = new Object[a.length + 1];
..
return objArray2;
}
objArray is just a passed in reference argument to the method. It will not change external reference variables. The variable objArray is removed from the stack the moment the method is ended.
Assigning to a parameter has no affect on the matching argument, as opposed to modifying a parameter, which does.
Oh dear, where to start.
This method is void and doesn't throw or side-effect, therefore it does nothing.
The statement objArray[i] = objArray[i]; has no effect.
a is not declared (or you haven't shown us enough context).

Object Reference passing in Java. Pass by reference working differently in different case?

While playing in Java. I saw different behaviour if an object is modified and given a value and different value if it is assigned a new object. Here is code that I made to show the result.
public class Test {
int i;
public Test(int j) {
this.i = j;
}
public static void main(String[] args) {
Test A = new Test(5);
Test N = new Test(5);
add(A);
makeNew(N);
System.out.println("Value of A.i= "+A.i);
System.out.println("Value of N.i= "+N.i);
}
private static void add(Test t) {
t.i+= 3;
System.out.println("Inside method add() t.i= "+t.i);
}
private static void makeNew(Test t) {
t = new Test(8);
System.out.println("Inside method makeNew() t.i= "+t.i);
}
}
Here is the output of the above code.
Inside method add() t.i= 8
Inside method makeNew() t.i= 8
Value of A.i= 8
Value of N.i= 5
In above example object A is modified to value 8. And object B is given a new object itself. But calling them back only object A shows new value. Object B shows the old value itself. Should not they be showing same value because both case are pass by refernce? I was expecting same value for A.i and N.i.
Here's what happens:
Test A = new Test(5);
Test N = new Test(5);
add(A); // method is add(Test t)
makeNew(N)// method is makeNew(Test t)
t = new Test(8);
System.out.println("Value of A.i= "+A.i);
System.out.println("Value of N.i= "+N.i);
Whenever you make a variable equal to an object and later use new on that object somewhere else like through another reference, your variable you set to the objects reference no longer points to whatever the new object is, but still holds onto the old. So if multiple variables at different scopes hold a reference, they all need a way to have them made equal to whatever the new object is or they no longer are in synch.
I think this will make you doubt clear:
You see N still point to the first object
In your makeNew, you're overwriting the reference to the existing object (that's passed in as the paramter) with your new test(8) object. However, that's local inside makeNew, so the original object sitting inside main(...) is not affected.
Java is pass-by-value. You pass the reference of an object as a value, and you can thus modify that object. However, you cannot modify the actual reference of an object and make it point to something else.
Your question has already been answered here: Is Java "pass-by-reference" or "pass-by-value"?
In Java you do not pass the actual object nor do you pass the reference to the object. You pass copy of the reference to that object. Now when you say
makeNew(N);
N which is the reference to new Test(5) is not passed but the copy of it's reference is passed. In the makeNew() function this copy points to some new object and print the value appropriately but the N will still point to the original object.

Categories