Detailed explanation of the difference between Java basic data type passing and reference passing

This article is transferred from http://blog.csdn.net/javazejian/article/details/51192130


Java's pass-by-value and pass-by-reference are generally involved in interviews. Today we will talk about this issue. First of all, we must realize that this problem is generally relative to functions, that is, method parameters in java. Then Let's first review two technical terms used in programming languages ​​for passing parameters to methods (or functions):

  • call by value

  • call by reference

The so-called call-by-value means that the method receives the value provided by the caller, while the call-by-reference means that the method receives the variable address provided by the caller (in the case of C language, it is a pointer, of course, java does not have a pointer. concept). What we need to pay attention to here is that a method can modify the variable value corresponding to the pass-by-reference, but cannot modify the variable value corresponding to the pass-by-value call. This sentence is very important. This is the fundamental difference between call-by-value and call-by-reference . Of course, if I still don't understand, it doesn't matter, the following is a thorough analysis with pictures and texts.

Earlier we said that there is no call by reference in java, which is true, because the java programming language does use call by value, that is, call by value. That is, the method gets a copy of all parameter values, and the method cannot modify the contents of any parameter variables passed to it. Let's look at an example:

public class CallByValue {  
      
    private static int x=10;  
      
    public static void updateValue(int value){  
        value = 3 * value;  
    }  
      
    public static void main(String[] args) {  
        System.out.println("The value of x before the call: "+x);  
        updateValue(x);  
        System.out.println("The value of x after the call: "+x);  
    }  
      
}  

Running the program yields the following results:


You can see that the value of x has not changed. Next, let's take a look at the specific execution process:

                                

analyze:

1) value is initialized to a copy of the x value (that is, 10)

2) The value is multiplied by 3 and equals 30, but note that the value of x is still 10 at this time!

3) After the method ends, the parameter variable value is no longer used and is recycled.

Conclusion: It is not possible for a method to modify a parameter of a primitive data type when passing method parameter types of primitive data types (numbers and booleans).

Of course, in addition to basic data types in Java, there are also reference data types, that is, object references, so what about this data type? Let's still look at an example first:

Declare a User object type:

package com.zejian.test;  
public class User {  
    private String name;  
    private int age;  
    public User(String name, int age) {  
        this.name=name;  
        this.age=age;  
    }  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    public int getAge() {  
        return age;  
    }  
    public void setAge(int age) {  
        this.age = age;  
    }  
}  
The execution class is as follows:
public class CallByValue {  
    private static User user=null;  
    public static void updateUser(User student){  
        student.setName("Lishen");  
        student.setAge(18);  
    }  
      
      
    public static void main(String[] args) {  
        user = new User("zhangsan",26);  
        System.out.println("The value of user before the call: "+user.toString());  
        updateUser(user);  
        System.out.println("The value of user after calling: "+user.toString());  
    }  
}
The results are as follows:

Obviously, the value of User has been changed, that is to say, if the method parameter type is a reference type, the value corresponding to the reference type will be modified. Let's analyze this process:

                 

Process analysis:

1) The student variable is initialized as a copy of the user value, which is a reference to an object.

2) Call the set method of the student variable to act on the reference object, and the internal value of the User object referenced by both user and student is modified.

3) After the method ends, the student variable is no longer used and is released, while the user remains unchanged and still points to the User object.

Conclusion: When a method parameter type is passed as a reference data type, a method will modify the value of the object pointed to by a parameter of the reference data type.

虽然到这里两个数据类型的传递都分析完了,也明白的基本数据类型的传递和引用数据类型的传递区别,前者将不会修改原数据的值,而后者将会修改引用所指向对象的值。可通过上面的实例我们可能就会觉得java同时拥有按值调用和按引用调用啊,可惜的是这样的理解是有误导性的,虽然上面引用传递表面上体现了按引用调用现象,但是java中确实只有按值调用而没有按引用调用。到这里估计不少人都蒙逼了,下面我们通过一个反例来说明(回忆一下开头我们所说明的按值调用与按引用调用的根本区别)。

public class CallByValue {  
    private static User user=null;  
    private static User stu=null;  
      
    /** 
     * 交换两个对象 
     * @param x 
     * @param y 
     */  
    public static void swap(User x,User y){  
        User temp =x;  
        x=y;  
        y=temp;  
    }  
      
      
    public static void main(String[] args) {  
        user = new User("user",26);  
        stu = new User("stu",18);  
        System.out.println("调用前user的值:"+user.toString());  
        System.out.println("调用前stu的值:"+stu.toString());  
        swap(user,stu);  
        System.out.println("调用后user的值:"+user.toString());  
        System.out.println("调用后stu的值:"+stu.toString());  
    }  
}  
我们通过一个swap函数来交换两个变量user和stu的值,在前面我们说过,如果是按引用调用那么一个方法可以修改传递引用所对应的变量值,也就是说如果java是按引用调用的话,那么swap方法将能够实现数据的交换,而实际运行结果是:

我们发现user和stu的值并没有发生变化,也就是方法并没有改变存储在变量user和stu中的对象引用。swap方法的参数x和y被初始化为两个对象引用的拷贝,这个方法交换的是这两个拷贝的值而已,最终,所做的事都是白费力气罢了。在方法结束后x,y将被丢弃,而原来的变量user和stu仍然引用这个方法调用之前所引用的对象。

            

这个过程也充分说明了java程序设计语言对对象采用的不是引用调用,实际上是对象引用进行的是值传递,当然在这里我们可以简单理解为这就是按值调用和引用调用的区别,而且必须明白即使java函数在传递引用数据类型时,也只是拷贝了引用的值罢了,之所以能修改引用数据是因为它们同时指向了一个对象,但这仍然是按值调用而不是引用调用。

总结:

  • 一个方法不能修改一个基本数据类型的参数(数值型和布尔型)。

  • 一个方法可以修改一个引用所指向的对象状态,但这仍然是按值调用而非引用调用。

  • 上面两种传递都进行了值拷贝的过程。


    参考资料:java核心卷1


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325725924&siteId=291194637