In Java, is it passed by value or by reference? The swap function tells you

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 intof the asum bof 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 asum here is bjust a copy of the sum , Aand Bthe result of the function does not change the original Asum Bvalue.

What about adoption Integer?

If the above inttype 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 Integerthe source code:

public final class Integer extends Number implements Comparable<Integer> {
    
    }

You can see the Integeruse of finalmodified intstorage. finalModified 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 arrayis a reference to the object arrcopy, not the copy of the object itself, therefore, arrayand arrpointing 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?

  1. 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
  1. 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);
}

Guess you like

Origin blog.csdn.net/weixin_44471490/article/details/109153085