Java. Argument does not change - java

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.

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.

How is Java parameter reference and original reference (not object) the same? [duplicate]

This question already has answers here:
What is the difference between a variable, object, and reference? [duplicate]
(5 answers)
Closed 5 years ago.
So we know that Java uses pass by value, i.e. it passes a copy of the reference to the methods.
I am wondering why is it then, that when I test the parameter reference (param in my example) with the original reference (string in my example) is says they are the same?
Shouldn't the following code return false, i.e. the references are not the same, because a copy reference (i.e. a new reference) is passed by value?
public class Interesting {
private String string;
public Interesting(final String interestig) {
super();
string = interestig; // original reference is tested against copy reference and it says they are the same
}
public boolean isItTheSame(final String param) {
return param == string;
}
public static void main(final String args[]) {
Interesting obj = new Interesting("String");
System.out.println(obj.isItTheSame(obj.string)); //copy of reference is created here
}
}
A reference variable is a reference. It contains a specific bit pattern​ that identifies the location of an object. This is known in computer science as a pointer. Per the JLS, "reference values (often just references) are pointers to these objects". Pointer values, like primitives, are passed to methods just by their bit pattern. That same pattern means they point to the same object. That's what == checks, whether two pointers point to the same object. That's why you get that result.
No, because == compares the value of the reference as well; it yields true if both references refer to the same object.
A reference is a value of its own. The string "String" lives at a specific memory location, say 0x01ab64e. Therefore, the value of any reference referring to that string is 0x01ab64e. There can be no reference to that string with a different value, because then it will not be referring to that string, it will be referring to a different string.
"Pass by value" refers to passing the reference by value, not passing the actual referenced object (the string) by value. So, the exact same reference is passed. That's why it is the same.
To verify that the reference is passed by value, (and that the value is a copy,) try this:
String s = null;
foo( s );
assert s == null;
void foo( String s )
{
s = "not null";
}
The assertion does not fail, which means that the reference s held by the caller was not altered. Which means that the reference s was passed by value, (which is always a copy,) so foo() only changed the value of its own copy of the reference, leaving the copy of the caller unaffected.

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.

Advance for reference variables?

I am trying to understand the difference between Object with primitive variables when using them as parameters in a method.
There are some examples using reference variables:
public class Test1 {
public static void main(String[] args) {
int[] value = {1};
modify(value);
System.out.println(value[0]);
}
public static void modify(int[] v) {
v[0] = 5;
}
}
result: 5
public class Test2 {
public static void main(String agrs[]) {
Integer j = new Integer(1);
refer(j);
System.out.println(j.intValue());
}
public static void refer(Integer i) {
i = new Integer(2);
System.out.println(i.intValue());
}
}
result: 2 | 1
So what is different in here?
In java array is primitive type.and Integer is Object type.
For primitives it is pass by value the actual value (e.g. 3)
For Objects you pass by value the reference to the object.
In first example,
you are changing value in array.
while in other example ,
you are changing reference of i to other memory location where object value is 2.
when returning back to main function, as you are not returning value. its reference scope limited to "refer" method only.
Recall that the array references are passed by value. The array itself is an object, and that's not passed at all (That means that if you pass an array as an argument, your'e actually passing its memory address location).
In modify() method, you're assigning 5 to the first place in the array, hence, changing the array's value. So when you print the result, you get: 5 because the value has been changed.
In the second case, you're creating a new Object of type Integer locally. i will have the same value when you exit the method refer(). Inside it you print 2, then you print i, which is 1 and hence change doesn't reflect.
v[0] = 5, is like saying Get 0th element of current v's reference and make it 5.
i = new Integer(2), is like saying change i to 2's Integer object reference
In one case you are changing the internal values via the reference and in latter you are changing the reference itself.
The difference here is that they are different.
In your first example you are passing the argument to another method, which is modifying one of its elements, which is visible at the caller. In the second case you are assigning the variable to a new value, which isn't visible at the caller, because Java has pass-by-value semantics.
NB 'Primary variable' has no meaning in Java.
I don't know what the word 'advance' in your title has to do with anything.

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 !

Categories

Resources