为什么 java 中只有值传递

本贴最后更新于 1882 天前,其中的信息可能已经沧海桑田

值传递 || 引用传递??

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

引用传递(pass by reference):是指在调用函数的时候将实际参数的地址直接传递到函数中,那么在函数中对参数的修改,将影响到实际参数。

区别:值传递会创建副本,引用传递不会

到底是什么传递?

关于 java 中的参数传递是值传递还是引用传递的问题,对于我这个新手来说的确是十分恼火的,之前我的不确定理解(...反正不清楚)是如果传递的参数是普通类型,那就是值传递,如果是对象,那就是引用传递。而在我看到 Hollis 的关于这个问题的讲解时,我豁然开朗,原来 java 中只有值传递呀。

为什么会存在参数是对象类型的时候是引用传递的理解呢?因为有代码证明呀 ~~~(事实是举例不当)

例子 1

public class Test{
public static void main(String[] args){
 Test test=new Test();
    Elployee elployee=new Employee();
    elployee.setName("elployee-A");
    elployee.pass(elployee);
    System.out.println("print in main,user is "+elployee);
}
    public void pass(Employee elployee){
    elployee.setName("elployee-B")
    System.out.println("print in pass,user is "+elployee);
    }
}

输出结果如下:

print in pass,user is {name='elployee-B'}

print in main,user is {name='elployee-B'}

经过 pass 方法后,实参的值竟然被改变了,那么按照上面的引用传递的定义,这不就是引用传递了么,所以有人就得出了在 java 的方法中,传递的是对象类型的时候是引用传递。

但是,这种表述事实上是错误,我们接着看下面一个同样是对象作为参数的情况

例子 2

public class Test{
public static void main(String[] args){
 Test test=new Test();
    Elployee elployee=new Employee();
    elployee.setName("elployee-A");
    elployee.pass(elployee);
    System.out.println("print in main,user is "+elployee);
}
    public void pass(Employee elployee){
    elployee=new Employee();
    elployee.setName("elployee-B")
    System.out.println("print in pass,user is "+elployee);
    }
}

输出结果:

print in pass,user is {name='elployee-B'}

print in main,user is {name='elployee-A'}

在上面的 pass 中改变了 elployee 对象,如果是引用传递的话那么在输出应该跟例子 1 一样呀,但是并不一样,这是为什么呢?

事实上在上面的过程中,当我们调用 pass 方法的时候,并把 elployee 作为实际参数传递给形式参数 elployee 的时候,会把实际参数的地址给形式参数,这时形式参数也指向了实际参数的地址。所以在例子 1 中,我们对形式参数的属性进行修改的时候会影响到实际参数,因为此时形式参数持有的地址就是直接参数的地址。而在例子 2 中,形式参数得到实际参数的地址后,我们又对形式参数重新分配一个对象实例,此时形式参数不在只有实际参数的地址,而是持有新建立的对象的地址。

也就是说,这里实际是把实际参数的地址复制了一份,传递给了形式参数。所以这个过程其实是值传递,把实际对象的地址当做了值传递给了形式参数。

更加详细的内容:https://mp.weixin.qq.com/s/F7Niaa7nD1tLApCEGKAj4A

原来是值传递呀!

在了解到 Java 中只有值传递后,脑海中又浮现出好像看到过相关知识的情节。于是再去翻 java 核心技术卷 I 的时候,发现在关于方法参数的那一节讲过这个问题,其中给出了如下例子。

public static void swap(Employee x,Employee y){
    Employee temp=x;
    x=y;
    y=temp;
}
public static void main(String[] args){
Elployee a=new Employee("Alice",...);
Elployee b=new Employee("Bob",...);
swap(a,b);
}

执行 swap(a,b)后,a 仍然是 Alice 而 b 仍然是 Bob。

由此也可以看出参数传递的方式为值传递。

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3190 引用 • 8214 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • nobt
    String str = "abc";
    str.replace("b","d");
    System.out.println(str);
    
    
  • Blackman99 1 赞同

    当你使用一个符号、字母、数字的组合去储存某一个值的时候,就没有值传递了,所有的变量都是对值的引用

  • someone
    作者

    没有值传递了?不太清楚你具体说的什么例子。

  • Blackman99

    我一直觉得“值传递”这个说法从根本上就是不正确的,任何编程语言都只是使用变量去指向内存地址,根本没有什么“值传递”。现在普遍被接受的“值传递”的概念只不过是指向了同一个内存地址。

  • someone
    作者

    先给出一个名词,求值策略。首先明确不管是值传递还是引用传递都是一种求值策略,越过了求值策略而去谈具体的求值方式,我觉得意义不大。求值策略是计算机科学上的一个概念,wiki 是这样说的, 求值策略是确定编程语言中表达式的求值的一组(通常确定性的)规则。在了解求值策略是什么后,再谈编程语言中有没有值传递,值传递到底是什么?我觉得比较合理一些。另,任何编程语言都只是使用变量去指向内存地址,这句话我只可以理解到,在编程语言中,是怎么通过一个变量名得到变量的具体的值。我并不能看出这跟值传递有什么关系。又怎么说明了值传递不存在。关于最后一句“值传递”的概念只不过是指向了同一个内存地址,我觉得这是没有理解到值传递的本质,才会这样去理解。值传递与引用传递的本质区别在于有没有拷贝,这跟指向是否同一个内存地址并无关系。