Java - Object state does not change after method call [duplicate] - java

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 6 years ago.
Beginner java question, but I cannot understand how call-by-Value ( or Reference ) is working in the example below -
How come the String value is not modified after it exits the method while my custom String Object is. ? Same with other classes like Date..
public class StringMadness {
public static void main(String[] args) {
String s = "Native String";
CustomStringObject cs = new CustomStringObject();
System.out.println("Custom String Before: " + cs.str);
hello(cs);
System.out.println("Custom String After: " + cs.str);
System.out.println("Native String Before: " + s);
hello(s);
System.out.println("Native String After: " + s);
}
private static void hello(String t) {
t = "hello " + t;
}
private static void hello(CustomStringObject o) {
o.str = "hello " + o.str;
}
}
class CustomStringObject {
String str = "Custom String";
}

Compare these two methods:
private static void hello(String t) {
t = "hello " + t;
}
private static void hello(CustomStringObject o) {
o.str = "hello " + o.str;
}
In the first case, you're assigning a new value to t. That will have no effect on the calling code - you're just changing the value of a parameter, and all arguments are passed by value in Java.
In the second case, you're assigning a new value to o.str. That's changing the value of a field within the object that the value of o refers to. The caller will see that change, because the caller still has a reference to that object.
In short: Java always uses pass by value, but you need to remember that for classes, the value of a variable (or indeed any other expression) is a reference, not an object. You don't need to use parameter passing to see this:
Foo foo1 = new Foo();
Foo foo2 = foo1;
foo1.someField = "changed";
System.out.println(foo2.someField) // "changed"
The second line here copies the value of foo1 into foo2 - the two variables refer to the same object, so it doesn't matter which variable you use to access it.

There's an important difference between the two methods: using hello(String) you're trying to change the reference to the String, and with hello(CustomObject), given a reference, you're using the reference to change a member of the object.
hello(String) takes a reference to a String. In the function you're trying to change which object that reference points to, but you're only changing the pass-by-value copy of the reference. So your changes aren't reflected outside the method.
hello(CustomObject) is given a copy of a reference to an object, which you can then use to change the actual object. Think of this as changing the contents of the object. So your changes are reflected in the caller.
Given a reference to an object, you can change the object using it's exposed methods/fields

Because for the String you are just changing the local parameter reference.

t will point to new object and scoped to method only, so changes not visible outside.
Second case, the value you are changing will be updated to object,so those changes are visible after method call.

Doesn't work because String is an immutable object

Related

Passing object in Java and try to change them in many ways [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 3 years ago.
I know a little bit about how Java is pass by value, and how passing a object to a method can change the object's field (ex. change1() in the Car class).
However, my question is why change2() and change3() don't change anything (especially change3())
public class question {
public static void main(String[] args)
{
Car c1 = new Car(1000,"Hyundai");
Car c2 = new Car(2000,"BMW");
c1.change3(c1);
c1.change3(c2);
System.out.println(c1.name + " "+ c1.price );
System.out.println(c2.name + " " + c2.price);
}
}
class Car
{
int price;
String name;
Car(int p , String n)
{
this.price=p;
this.name=n;
}
void change1(Car c)
{
c.price=0;
c.name="Changed";
}
void change2(Car c)
{
c = new Car(999,"Honda");
}
void change3(Car c)
{
c = new Car(888,"Audi");
c.price=80;
c.name="xxx";
}
}
Every time JVM executes new operator, a new Object/Instance is being created. You are creating a new object of the Car type in your change3(Car c) method and storing the reference on that object into local variable c. After this, anything you set on that c is amending new object, and not the one you passed a reference of.
void change3(Car c) //receives the reference to the object you pass;
{
c = new Car(888,"Audi"); //creates a new Car object and assigns reference to that **new object** to the variable c.
c.price=80; //here, you're changing the price/name fields of different object.
c.name="xxx";
}
Pay attention, that in change1(Car c) you do not create a new object, but in change2(Car c) and change3(Car c) - you do [explicitly] create new objects.
Edited:
Java is pass by value for primitives and for objects, it's a copy of the original reference.
To be more specific it's a copy of the same reference, which means that is a different pointer to the same reference of the same object, so if you change the object in your method, the original object is going to change too. BUT if you assign it again (with the new operator in your case) , you are going to update your pointer inside your method to a new reference, but the original pointer remains as it was.
Another about probably most upvoted question about Java on StackOverflow :)
The pass by value or reference probably comes from the understanding and conventions used in C++ language.
The types of parameters are passed by value.
But when passing an object it doesn't pass the whole object, but a copy of address in memory (aka reference) pointing to that object.
Passing parameter by reference means it's possible to change that parameter inside of an method and that change would be visible outside of that method.
Java in "passed by value" because changing/reassigning the passed parameter isn't visible outside of an method.
In the case of:
void change1(Car c)
{
c.price=0;
c.name="Changed";
}
The assignments to price and name are visible outside of that method, because the the method changes the member fields of the passed instance and not the instance itself.
The change2 and change3 methods doesn't reflect outside of them because of reassigning the passed c parameter.
When reassigning passed object, the address behind passed object parameter no longer points to the same object as originally passed one.
Similary, it's not possible to reflect the change or reassigning of passed primitive or:
void change4(String name) {
name = "whoopsie";
}
//and later calling it with:
c1.change4(c1.name);
Changing the inner state of an object isn't the same as changing the object itself.

Creating a new object (in another method) for one which is already existing [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 4 years ago.
Please explain me why am i getting an output
1234567 7654321
I want to know what exactly is happening here.
public static void main(String[] args) {
Date date = new Date(1234567);
m1(date);
System.out.print(date.getTime() + " ");
m2(date);
System.out.println(date.getTime());
}
public static void m1(Date date) {
date = new Date(7654321);
}
public static void m2(Date date) {
date.setTime(7654321);
}
What you do in m1 is make the variable date point at a new object. But this variable exists only inside the scope of the method m1. The date variable inside your main method is a different one.
This is your code just with renamed variables
public static void main(String[] args) {
Date var1 = new Date(1234567);
m1(var1);
System.out.print(var1.getTime() + " ");
m2(var1);
System.out.println(var1.getTime());
}
public static void m1(Date parameter) {
parameter = new Date(7654321);
}
public static void m2(Date parameter) {
parameter.setTime(7654321);
}
As you can see your method m1 only changes the value of parameter, not of the original var1. This method doesn't access the object which the variable parameter is pointing at but instead makes the variable point at a new object which has nothing to do with the object which was passed from var1.
m2 is not creating a new object. It is accessing the object which the variable parameter points at and calls the setTime(...) function to change attributes of the object. Since the object of parameter and var1 is still the same here, var1 later references the object which has been modified and the changes are "visible" to you.
It is a common miss assumption of young oop developers that objects and variables are one and the same. Objects are instances of classes created into the ram of your computer. Variables are just simply referencing those objects (accessing them through their memory address) and reading/writing from their memory. The same object can be referenced by multiple variables tho
// here both variables are pointing at the same object
Date var1 = new Date();
Date var2 = var1;
// this change is done to one object, referenced by both variables
var1.setTime(180128);
// Since both point at the same object, the output is exactly the same
System.out.println(var1);
System.out.println(var2);
// now we point var2 at a different object, the same one as var3
Date var3 = new Date();
var2 = var3;
// Var1 will still be the same as before. But var2 will match var3
System.out.println(var1);
System.out.println(var2);
System.out.println(var3);
So you see variables are not the same thing as objects. And a parameter of a method is also just another variable which points at the object that was passed to the method when it was called. Changing the object it is pointing at does not do any changes to the object it originally was pointing at.

While passing an object reference to a method in java members are updating but reference remains the same. Why? [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
info.name and info.phone are changing after passing to defaultEntry(Info infoObject) but reference not changing to null why? can anybody please explain this scenario as well as working of java methods. Is there any difference between c functions and java methods working mechanism?
Thanks in advance :)
class Info {
String name = "Sagar Pudi";
String phone = "9999999999";
}
public class MemberDetails {
public void defaultEntry(Info infoObject) {
infoObject.name = "DEFAULT_MEMBER";
infoObject.phone = "NO_PHONE";
infoObject = null;
}
public static void main(String[] args) {
Info info = new Info();
System.out.println("Before : " + info.name + "<->" + info.phone);
MemberDetails md = new MemberDetails();
md.defaultEntry(info);
System.out.println("After : " + info.name + "<->" + info.phone);
if (info != null)
System.out.println("info is still an object of " + info.getClass());
}
}
Output:
Before : Sagar Pudi<->9999999999
After : DEFAULT_MEMBER<->NO_PHONE
info is still an object of class Info
Java's references are passed by value. i.e., the reference itself is copied.
So whatever changes you do to the passed reference (not the object the reference refers to) will not be reflected on the original object reference.
Take a look at the AtomicReference<T> class wrapper. This is what you'll want. When modifying an object from within a function you cannot directly null the reference (you are essentially working with a copy of a pointer to the object, so nulling that will not do a thing to the caller of your method).
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicReference.html
public void defaultEntry(Info infoObject) {
infoObject.name = "DEFAULT_MEMBER";
infoObject.phone = "NO_PHONE";
infoObject = null;
}
becomes
public void defaultEntry(AtomicReference<Info> atomicInfoObject) {
atomicInfoObject.get().name = "DEFAULT_MEMBER";
atomicInfoObject.get().phone = "NO_PHONE";
atomicInfoObject.set(null);
}
On that same note, the mutability of arrays and lists also allows for abuse you could do the same with
public void defaultEntry(Info[] infoObject) {
infoObject[0].name = "DEFAULT_MEMBER";
infoObject[0].phone = "NO_PHONE";
infoObject[0] = null;
}
Here you have two references(infoObject,info) for one object(Info),because java references are pass by value.
Making a reference null means,it does not point to any object. So in your case if you assign null to infoObject variable, the info variable will still continue holding references to Info class object.
There is no "Pass by reference" concept in java. References also copied using "Pass by value" strategy. Here in the above case, variable "info" (reference value) is copied to "infoObject" in the called method. So while method body is executing (from the calling to the return from the function), we have two reference variables "info" and "infoObject" ideally pointing to the same data object in memory. So if we made change to any of the object data, it get reflected in both the objects. when you made
infoObject = null;
it just makes that reference variable to be de-reference. Still variable "info" holds the valid object.

String in Java is object, so it should be reference? [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
I am a beginner in Java, recently faced such an interview question on Java String concept:
public class Test1 {
public static void changeStr(String str){
str="welcome";
}
public static void main(String[] args) {
String str="1234";
changeStr(str);
System.out.println(str);
}
}
I think the output should be "welcome", however, I tested it in Eclipse, it showed "1234", isn't Java string is a reference, so the Java string "str" references gets changed to "welcome" in method changeStr?
Pardon me for the beginner question!
The object's reference is passed to the method and assigned to the parameter, which is a kind of local variable.
Assigning a different object reference to the parameter does nothing to the variable outside the method that held a reference to the original object.
Also String is immutable, so there's no way to change its value (for example a setValue() method).
The line str = "welcome"; doesn't change the value of any String - Strings can never change their values. What it does is it makes one reference point to a different String. But the reference that it reassigns is the one that's local to changeStr, not the one that is declared in main.
String is a reference, but the key is that String str inside changeStr is a different reference than str in main. Add that to the fact that strings are immutable in Java (meaning that when you change a String, the reference points to a different location in memory) and that explains why main will print 1234
Consider the following example:
public static void main(final String[] args) throws Exception {
final StringHolder holder = new StringHolder("old value");
System.out.println(holder);
reassignHolder(holder);
System.out.println(holder);
changeVal(holder);
System.out.println(holder);
}
static void reassignHolder(StringHolder holder) {
holder = new StringHolder("new value");
}
static void changeVal(StringHolder holder) {
holder.setVal("new value");
}
static class StringHolder {
private String val;
public StringHolder(String val) {
this.val = val;
}
public String getVal() {
return val;
}
public void setVal(String val) {
this.val = val;
}
#Override
public String toString() {
return "StringHolder{" + "val=" + val + '}';
}
}
In Java references are passed by value and (almost) everything is an object reference.
Here we have a mutable object that holds a String - a StringHolder.
When we call reassignHolder what we actually do is copy our object reference and pass it to the method. When the method reassigns the reference nothing happens to our original reference as we are passing a copy.
When we call reassignHolder we also pass a copy of our reference, but the method uses this reference to call a method on our object to change its val variable. This will have an effect.
So the output is:
StringHolder{val=old value}
StringHolder{val=old value}
StringHolder{val=new value}
As String is immutable, you can only carry out the first example rather than the second.
The logic here is that the str value that is passed is passed as a copy of reference of str. This implies that any change in str will not be reflected in the original str.
This situation is similar to pass by value (but of references!)
However in your code if you change the code to str = new String("welcome"); It will change the original str string by making it reference a new copy that was created.
Hope this clears things for you.

Java. Argument does not change

static void f(String s)
{
s = "x";
}
public static void main(String[] args) {
String s = null;
f(s);
}
Why the value of s after calling f(s) is null instead of "x"?
Because s is a reference. You pass a copy of that reference to the method, and then modify that copy inside the method. The original doesn't change.
When passing an Object variable to a function in java, it is passed by reference. If you assign a new value to the object in the function, then you overwrite the passed in reference without modifying the value seen by any calling code which still holds the original reference.
However, if you do the following then the value will be updated:
public class StringRef
{
public String someString;
}
static void f(StringRef s)
{
s.someString = "x";
}
public static void main(String[] args)
{
StringRef ref = new StringRef;
ref.someString = s;
f(ref);
// someString will be "x" here.
}
Within the function f() the value will be "x". Outside of this function the value of s will be null. Reference data types (such as objects) are passed by value see here (read the section "Passing Reference Data Type Arguments")
Given that s is of type String, which is a reference type (not a primitive):
s = "x";
does not mean "transform the thing that s refers to into the value "x"". (In a language where null is a possibility, it can't really do that anyway, because there is no actual "thing that s refers to" to transform.)
It actually means "cause s to stop referring to the thing it currently refers to, and start referring to the value "x"".
The name s in f() is local to f(), so once the function returns, that name is irrelevant; the name s in main() is a different name, and is still a null reference.
The only thing that the parameter passing accomplishes is to cause s in f() to start out as null.
This explanation would actually go somewhat more smoothly if you hadn't used null :(
Actually you are not changing the value you are creating new one, it is totally different, If you change an attribute of the abject in the method then i will be changed in your references. But you are creating new object.

Categories

Resources