Argument values handled by Java methods are passed by value for basic types and passed by reference for reference types. However, when this story comes up, there are some questions that I don't understand the behavior of String.
Well, I wish I could explain that.
For basic types, it is passed by value. So the value is copied and passed. It does not pass the value itself. This means that the value of the passed variable does not change before and after passing it to the method.
//Example 1
public class PrimitiveType {
public static void main(String[] args) {
PrimitiveSample ps = new PrimitiveSample();
int i = 5;
System.out.println("Value before change of main method: " + i);
ps.changeInt(i);
System.out.println("Modified value of main method: " + i);
}
}
class PrimitiveSample {
public int changeInt(int i) {
System.out.println("Value before change with changeInt: " + i);
i = i + 10;
System.out.println("Value after change with changeInt: " + i);
return i;
}
}
Value before change of main method: 5
Value before change with changeInt: 5
Value after change with changeInt: 15
Modified value of main method: 5
In the case of the reference type, it is actually "pass by value" because it "copy and pass the referenced address of the reference type".
In other words, if you copy and hand over a memo with "Address of 1 Sakuragaoka-cho, Shibuya-ku, Tokyo" and use the copy of the memo to "Send a letter to the address of 1 Sakuragaoka-cho, Shibuya-ku, Tokyo" , "Address of 1 Sakuragaoka-cho, Shibuya-ku, Tokyo" will receive the letter. However, even if you tear the copy of the memo, it will not affect the "Address of 1 Sakuragaoka-cho, Shibuya-ku, Tokyo".
//Example 2
public class PointerType {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
sb.append("AIUEO");
System.out.println("Value before change of main method: " + sb.toString());
PointerSample ps = new PointerSample();
ps.appendData(sb);
System.out.println("Value before change of main method: " + sb.toString());
ps.deleteObject(sb);
System.out.println("The object of the main method does not disappear: " + sb.toString());
}
}
class PointerSample {
public void appendData(StringBuffer sb) {
System.out.println("Value before change in appendData: " + sb.toString());
sb.append("Kakikukeko");
System.out.println("Value after change with appendData: " + sb.toString());
}
public void deleteObject(StringBuffer sb) {
sb = null;
}
}
Value before change of main method:AIUEO
Value before change in appendData:AIUEO
Value changed by appendData:Aiue Okakikukeko
Value before change of main method:Aiue Okakikukeko
The object of the main method does not disappear:Aiue Okakikukeko
So far, I think we've talked about it so far. In the first place, the word "pass by reference" is not good, and "passing by value of the reference destination" is correct, and there are other people who say so. I don't know much about Java, but when I asked someone who was good at C and C ++, he declared, "This is by value." it's interesting.
So, when String or Integer comes out, there is a mysterious argument that "Although the reference type is passed by reference, the value of String does not change. This is passed by value", but considering the above story in the first place It all ends with "passing the reference type by value of the reference destination".
To go a little further and explain ** String type has no function to change the object itself **, it is treated as a constant. Same as Integer type. There is no function to modify the object itself. There is no function like List or StringBuffer that "adds a value to your object and changes the contents of the object".
//Example 3 that is not refreshing
public class StringType {
public static void main(String[] args) {
StringSample ss = new StringSample();
String str = "AIUEO";
System.out.println("Value before change of main method: " + str);
ss.changeString(str);
System.out.println("Modified value of main method: " + str);
}
}
class StringSample {
public void changeString(String str) {
System.out.println("Value before change with changeString: " + str);
str = str + "Kakikukeko";
System.out.println("Value after change with changeString: " + str);
}
}
Value before change of main method:AIUEO
Value before change with changeString:AIUEO
Value after change with changeString:Aiue Okakikukeko
Modified value of main method:AIUEO
If you look only at Example 3, it will look the same as Example 1 and you will say "pass by value".
In fact, you have to check the contents of str = str +" Kakikukeko ";
.
System.identityHashCode (obj) is not a panacea, but it can be used for this kind of research. If you try to incorporate it into your business, you have to keep in mind that there may be duplication, but if the value changes, it is good to see that the object itself has changed.
public class StringType {
public static void main(String[] args) {
StringSample ss = new StringSample();
String str = "AIUEO";
System.out.println("Value before change of main method: " + str);
System.out.println("Hash 1 in main:" + System.identityHashCode(str));
ss.changeString(str);
System.out.println("Modified value of main method: " + str);
System.out.println("Hash 2 in main:" + System.identityHashCode(str));
}
}
class StringSample {
public void changeString(String str) {
System.out.println("-------");
System.out.println("Value before change with changeString: " + str);
System.out.println("Hash 1 in changeString:" + System.identityHashCode(str));
System.out.println("-------");
str = str + "Kakikukeko";
System.out.println("Value after change with changeString: " + str);
System.out.println("Hash 2 in changeString:" + System.identityHashCode(str));
System.out.println("-------");
}
}
Value before change of main method:AIUEO
Hash 1 in main:2018699554
-------
Value before change with changeString:AIUEO
Hash 1 in changeString:2018699554
-------
Value after change with changeString:Aiue Okakikukeko
Hash 2 in changeString:1311053135
-------
Modified value of main method:AIUEO
Hash 2 in main:2018699554
The hash in main is "2018699554", but in changeString there are "2018699554" and "1311053135". If there is no change in the argument str, it matches the hash value in main, but the object has changed when the str value is changed.
In other words, instead of changing from the original "2018699554", a new object "1311053135" is created and "Aiue Okakikukeko" is referenced there.
This is the same as in Example 2, "Breaking a copy of a note". In terms of str, it's just the difference between "inserting null" and "inserting a new object".
If the String type had a method like "change the value of its own object", it wouldn't have been such a confusing controversy. Conversely, the String type also holds that an object once set is invariant until another object is assigned.
I sometimes cry when I say that an array must be passed by value because it is an int type array, but since an array is a real object, it is good to think of it in the same way as other reference types. I don't think it's that difficult if you think of the basic type as a box of objects that can be put inside.
Passing by reference is not good because it makes the image look like passing the reference value of the object itself. It was a story.
Recommended Posts