How does String works as Object in Java - java

I am quite confused with how Object works in Java since I run into this problem.
Let's say I have a function called checkDateValue (code looks like this)
private boolean checkDateValue(Date d1, String msg) {
if (d1 == null) {
msg = "d1 is null!";
return false;
}
return true;
}
Here is the place I call this function:
String msg = null;
Date d1 = null;
if (!checkDateValue(d1, msg)) {
system.println(msg); //msg is still null.....
//what I need is the message generated in the function
}
As far as I know, if I put a customized Object
(e.g.
myObj { private String msg;}
)
into a function, and we change the value of msg inside the function, when we get out of the function, the change of msg is kept. However, I think String is also considered as an Object in java. Why the change is not kept?

Java doesn't have "out" function arguments; they are copies of references.
Even though you change msg in the function, it does not affect the caller's variable.

String is special, is immutable and is diffrent from normal Object.
Java's String is designed to be in between a primitive and a class.
String is passed by value, but unfortunately every change on String make new value, so your old reference has old value.
I think this is good explanation: https://stackoverflow.com/a/1270782/516167

In Java, you cannot pass back a value to calling code by assigning to a method parameter. You are right that you can alter the internal structure of any parameter and that change will be seen in the calling code. However, assigning to a parameter is not the same thing as altering the internal structure. Also, a String is immutable—once created, its internal structure cannot be altered.
A common trick to do what you what is to use an array argument:
private boolean checkDateValue(Date d1, String[] msg) {
if (d1 == null) {
msg[0] = "d1 is null!";
return false;
}
return true;
}
Then call it like this:
String[] msg = new String[1];
Date d1 = null;
if (!checkDateValue(d1, msg)) {
system.println(msg[0]);
}

This is related to the fact that
Java passes objects as references passed by value.
You can't change the reference argument to point to something else. You can change the object state.
You can read more here

msg = "d1 is null!"; and msg=null are two different String objects. Strings are immutable in Java.The reference is passed by value, i.e., a copy of the reference is passed. and since a String is immutable object , the assignment inside the method creates a new String object that the copy of the reference now points to. The original reference still points to the null String. Your method call is same as :
Object obj = null; // obj points to nowhere
foo(obj); // passed the reference values to method argument
void foo(Object o)
{
o = new Object( ); // o points to new Object, but obj still points to nowhere
}

if (!checkDateValue(d1, msg))
{
system.println(msg);
}
when you call checkDateValue method a reference String msg = null;
Date d1 = null; to the method
is passed which is pass by value. When method gets executed then
msg variable in checkDateValue will get referenced to "d1 is null!"
Here, msg variable in call remains same

Related

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.

Why is an ArrayList parameter modified, but not a String parameter? [duplicate]

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.

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

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

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.

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