Pass by value / Pass by reference
Value transfer : When the method is called, it 实参
is to assign a copy of itself 形参
. In the method, the modification of the parameter value does not affect the original actual parameter.
Passing by reference : when the method is invoked, 实参
to their 地址
transfer to 形参
, changes to the parameter values of the method of this time, the operation is the actual argument.
Only value passing in Java
First review some professional terms related to passing parameters to methods (or functions) in programming languages.
Call by value : Indicates that the method receives the value provided by the caller.
Call by reference : Indicates that the method receives the variable address provided by the caller.
It is used to describe the method parameter passing method in various programming languages (not just Java).
The Java programming language is always adopted 按值调用
. In other words, the method gets a copy of all parameter values, that is, the method cannot modify the contents of any parameter variables passed to it.
swap() scene
Request to write a function to exchange the value
int
of thea
sumb
of types
In the swap()
method, a, b values are exchanged, and does not affect the A, B. Because the values in a and b are just copied from A and B. In other words, a and b are equivalent to copies of A and B, and no matter how the content of the copy is modified, it will not affect the original itself.
If we write:
public class test{
public static void main(String[] args) {
int A = 2;
int B = 3;
swap(A, B);
System.out.println(A);
System.out.println(B);
}
public static void swap(int a, int b){
int tmp = a;
a = b;
b = tmp;
}
}
The running result is:
2
3
It is found that the values of A and B are not exchanged. Why?
Because what is used in Java is 值传递
, that is to say, during execution swap(int a, int b)
, the parameter a
sum here is b
just a copy of the sum , A
and B
the result of the function does not change the original A
sum B
value.
What about adoption
Integer
?
If the above int
type is changed to Integer
, swap(Integer a, Integer b)
will the exchange function be realized?
public class test{
public static void main(String[] args) {
Integer A = 2;
Integer B = 3;
swap(A, B);
System.out.println(A);
System.out.println(B);
}
public static void swap(Integer a, Integer b){
Integer tmp = a;
a = b;
b = tmp;
}
}
The running result is:
2
3
It can be seen that the exchange is still not completed!
To view Integer
the source code:
public final class Integer extends Number implements Comparable<Integer> {
}
You can see the Integer
use of final
modified int
storage. final
Modified variables cannot be reassigned, so when operating parameters to pass variables, it is actually an operation 变量对象的副本
(package types in Java are implemented in this way by default, and copying is used to improve efficiency and reduce memory consumption).
What if it is an array?
public static void main(String[] args) {
int[] arr = {
1, 2, 3, 4, 5 };
System.out.println(arr[0]);
change(arr);
System.out.println(arr[0]);
}
public static void change(int[] array) {
// 将数组的第一个元素变为0
array[0] = 0;
}
The running result is:
1
0
The method herein array
is a reference to the object arr
copy, not the copy of the object itself, therefore, array
and arr
pointing to the same array object.
What if it is a general object?
Many programming languages (especially C++ and Pascal) provide two ways to pass parameters: value call and reference call.
Some programmers (even the author of this book) think that the Java programming language 对象
uses reference calls. In fact, this understanding is incorrect. Since this misunderstanding has a certain generality, a counterexample is given below to elaborate on this problem.
class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
test:
public class test{
public static void main(String[] args) {
User A = new User("ali");
User B = new User("bd");
System.out.println("交换前name:" + A + "-->" + B);
swap(a,b);
System.out.println("交换后name:" + A + "-->" + B);
}
private static void swap(User a, User b) {
User tmp = a;
a = b;
b = tmp;
}
}
The running result is:
交换前name:ali-->bd
交换后name:ali-->bd
Found that there is still no exchange!
So whether there is any exchange depends mainly on whether it is modified 变量(引用)
or modified 堆里面的对象
.
Before exchange:
After the exchange:
It can be clearly seen from the above two pictures: The method does not change the object references stored in variables A and B. The parameters a and b of the swap() method are initialized as copies of two object references, and this method exchanges these two copies.
So how do we exchange the values of two variables?
- Use container (or array)
E.g:
public class test{
public static void main(String[] args) {
int[] arr = {
2, 3};
int A = arr[0];
int B = arr[1];
swap(arr, 0, 1);
A = arr[0];
B = arr[1];
System.out.println(A);
System.out.println(B);
}
public static void swap(int[] arr, int a, int b){
int tmp = arr[a];
arr[a] = arr[b];
arr[b] = tmp;
}
}
The running result is:
3
2
- With reflection
public static void swap(Integer a, Integer b) throws Exception {
Field field = Integer.class.getDeclaredField("value");
field.setAccessible(true); //设置可以访问成员的私有不可变的变量
Integer tmp =new Integer(a.intValue());
field.set(a, b.intValue());
field.set(b, tmp);
}