java的值传递

Java的值传递

原博客链接:为什么说Java中只有值传递

package com.liang.scanner;

public class Parameter {
    public static void main(String[] args) {
        //基本类型传递
        Parameter pt = new Parameter();
        int i = 10;
        pt.pass(i);
        System.out.println("print in main , i is " + i);
        //例1:实参、形参定义为基本类型时,输出I=10,J=20,java值传递
        

        //引用类型传递(对象)
        Parameter pt2 = new Parameter();
        User hollis = new User();
        hollis.setName("Hollis");
        hollis.setGender("Male");
        pt.pass(hollis);
        System.out.println("print in main , user is " + hollis);
        //例2:实参、形参定义为对象时,输出
        print in pass , user is User{name='hollischuang', gender='Male'}
		print in main , user is User{name='hollischuang', gender='Male'}
        java引用传递
        

        //引用类型传递(String)
        Parameter pt3 = new Parameter();
        String name = "Hollis";
        pt3.pass(name);
        System.out.println("print in main , name is " + name);
         //例3:实参、形参定义为String时,输出
     	print in pass , name is hollischuang
		print in main , name is Hollis
        java值传递    
        

        //引用类型传递(对象)
        Parameter pt4 = new Parameter();
        User hollis2 = new User();
        hollis2.setName("Hollis");
        hollis2.setGender("Male");
        pt.pass2(hollis2);
        System.out.println("print in main , user is " + hollis2);
        //例4:实参、形参定义为对象时,输出
        print in pass , user is User{name='hollischuang', gender='Male'}
		print in main , user is User{name='Hollis', gender='Male'}
        java值传递  
        

    }

    public void pass(int j) {
        j = 20;
        System.out.println("print in pass , j is " + j);
    }


    public void pass(User user) {
        user.setName("hollischuang");
        System.out.println("print in pass , user is " + user);
    }

    public void pass(String name) {
        name = "hollischuang";
        System.out.println("print in pass , name is " + name);
    }

    public void pass2(User user) {
        user = new User();
        user.setName("hollischuang");
        user.setGender("Male");
        System.out.println("print in pass , user is " + user);
    }


}



class User {
    private String name;
    private String gender;

    public void setGender(String gender) {
        this.gender = gender;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }
}

值传递:是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

引用传递:是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

上面,我们举了四个例子,表现的结果却不一样,那么值传递和引用传递之前的区别的重点是什么?

值传递 引用传递
根本区别 会创建副本 不会创建副本
所以 函数中无法改变原始对象 函数中可以改变原始对象

我们上面看过的几个pass的例子中,都只关注了实际参数内容是否有改变。如传递的是User对象,我们试着改变他的name属性的值,然后检查是否有改变。其实,在实验方法上就错了,当然得到的结论也就有问题了。

为什么说实验方法错了呢?这里我们来举一个形象的例子。再来深入理解一下值传递和引用传递,然后你就知道为啥错了

你有一把钥匙,当你的朋友想要去你家的时候,如果你直接把你的钥匙给他了,这就是引用传递。这种情况下,如果他对这把钥匙做了什么事情,比如他在钥匙上刻下了自己名字,那么这把钥匙还给你的时候,你自己的钥匙上也会多出他刻的名字。



你有一把钥匙,当你的朋友想要去你家的时候,你复刻了一把新钥匙给他,自己的还在自己手里,这就是值传递。这种情况下,他对这把钥匙做什么都不会影响你手里的这把钥匙。



但是,不管上面哪种情况,你的朋友拿着你给他的钥匙,进到你的家里,把你家的电视砸了。那你说你会不会受到影响?而我们在pass方法中,改变user对象的name属性的值的时候,不就是在“砸电视”么。你改变的不是那把钥匙,而是钥匙打开的房子。

上述例2和例4的内存分配过程

所以,值传递和引用传递的区别并不是传递的内容。而是实参到底有没有被复制一份给形参,例2中User对象输出的name值发生了改变,实际修改的是对象中name的引用地址,User对象中原Name字段持有的字符串并还没有发生改变,

所以说,Java中其实还是值传递的,只不过对于对象参数,值的内容是对象的引用。

posted @ 2022-03-21 20:39  梁小白123  阅读(125)  评论(0)    收藏  举报