Java中只存在值传递,调用函数赋值未修改异常

1、问题发生场景

定义函数A,此时在A中调用函数function(a),在function中,通过查找数据库,对a进行了重新赋值,此时A中的对象a值并未修改,如下场景模拟所示:

public class test {
    public static void main(String[] args) {
        Student student = new Student("小王", 18);
        function(student);
        System.out.println("此时学生对象为:" + student.toString());
    }
    
    private static void function(Student student){
        student = new Student("小明", 16);
    }
}

此时结果输出:此时学生对象为:Student(name=小王, age=18)

尽管在function()中对student对象进行了重新赋值,但是在main函数中的student对象并未修改。

2、未修改值分析

Java是具有值传递的,在传递过程中对不会对原有值产生影响

值传递:在传递过程中,将实际参数复制一份到调用函数中,在函数中对值进行修改,不会影响到实际参数。

引用传递:在传递过程中,将实际参数的地址传递给调用函数,在函数中对值进行修改,会影响到原有参数。

所以在上述代码中,function()函数尽管对st进行了重新赋值,但不会影响main函数中的st对象,也就造成了实际开发中,查数据库进行重新赋值后,未修改对象的情况

3、值传递测试

其中,student类包含name和age属性。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private String name;
    private Integer age;
}

3.1基本数据类型传递

public class test {
    public static void main(String[] args) {
        int i = 10;
        function(i);
        System.out.println("此时的对象i为:" + i);
    }
    
    private static int function(int i){
        i = 20;
        return i;
    }
}

此时结果输出:此时的对象i为:10

在传递过程中,对参数j进行了修改,但不影响main中的i值,与Java值传递原理相符合。

3.2引用类型传递

3.2.1传递对象值没有修改

在以下中,传递student对象,但是main函数中的值并未修改,与Java值传递原理相符合

public class test {
    public static void main(String[] args) {
        Student student = new Student("小王", 18);
        function(student);
        System.out.println("此时学生对象为:" + student.toString());
    }
    
    private static Student function(Student student){
        student = new Student("小明", 16);
        return student;
    }
}

此时结果输出:此时学生对象为:Student(name=小王, age=18)

3.2.2传递对象值被修改

在以下中,传递student对象,并调用set函数修改名字,后续值被修改

public class test {
    public static void main(String[] args) {
        Student student = new Student("小王", 18);
        function(student);
        System.out.println("此时学生对象为:" + student.toString());
    }
    
    private static Student function(Student student){
        student.setName("小明");
        return student;
    }
}

此时结果输出:此时学生对象为:Student(name=小明, age=18)

这是否与Java的值传递原理相违背呢?下面继续分析。

main函数中,传递的student对象值(此时值是对象的地址)。

拿到地址后,在function函数中,对该地址下的student对象中的name属性进行了修改,所以function中的setName会影响main中的student,他们指向堆中的地址是一致的

这也可以分析,在“传递对象值不修改”中,为什么不会对main中的student对象产生影响。

private static Student function(Student student){
    student = new Student("小明", 16);
    return student;
}

该函数中,直接把function中的student对象指向了new Sthdent。类似为好友复制了一把钥匙,他把这把钥匙锻造成了一把新的钥匙,但是不改变你身上的原有钥匙

4、解决未赋值方法

如果需要对main中的整个student对象进行同步更改,需要将function()函数中的st对象进行return,并在main函数中对st对象进行重新赋值。

public class test {
    public static void main(String[] args) {
        Student st = new Student("小王", 18);
        st = function(st);
        System.out.println("此时学生对象为:" + st.toString());
    }
    
    private static Student function(Student st){
        st = new Student("小明", 16);
        return st;
    }
}

此时结果输出:此时学生对象为:Student(name=小明, age=16)

这也是在代码设计中,我们调用方法都是以return方式得到该方法的返回结果,并进行重新赋值

在以下博客中有一个比喻非常清晰:java对象之间怎么实现值传递,“类似于好友复制了一把你家的钥匙,而他没有对钥匙进行刻字或修改,而是进入到家里,把家里电视给砸了”。这也就对应了传递对象值被修改的场景。

  • 22
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值