java到底是值传递还是引用传递?

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/asd199205/article/details/73167982
java中方法参数传递方式是按值传递
如果参数是基本类型,传递的是基本类型的字面值的拷贝

如果参数是引用类型,传递的是对象引用的拷贝

所谓值传递指的是将变量的一个备份传过去,当该备份被修改后,不会影响原来变量的值;(传递引用类型最多只能改变变量的参数,原因是方法改变通过copy地址改变变量的参数
而引用传递指的是将该变量的地址传过去,当值修改后,原来的变量也会相应的修改;

一:搞清楚 基本类型 和 引用类型的不同之处

int num = 10;
String str = "hello";


如图所示,num是基本类型,值就直接保存在变量中。而str是引用类型,变量中保存的只是实际对象的地址。一般称这种变量为"引用",引用指向实际对象,实际对象中保存着内容。

二:搞清楚赋值运算符(=)的作用

num = 20;
str = "java";

对于基本类型 num ,赋值运算符会直接改变变量的值,原来的值被覆盖掉。
对于引用类型 str,赋值运算符会改变引用中所保存的地址,原来的地址被覆盖掉。但是原来的对象不会被改变(重要)。
如上图所示,"hello" 字符串对象没有被改变。(没有被任何引用所指向的对象是垃圾,会被垃圾回收器回收)

三:调用方法时发生了什么?参数传递基本上就是赋值操作
第一个例子:基本类型
void foo(int value) {
    value = 100;
}
foo(num); // num 没有被改变

第二个例子:没有提供改变自身方法的引用类型
void foo(String text) {
    text = "windows";
}
foo(str); // str 也没有被改变

第三个例子:提供了改变自身方法的引用类型
StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) {
    builder.append("4");
}
foo(sb); // sb 被改变了,变成了"iphone4"。

第四个例子:提供了改变自身方法的引用类型,但是不使用,而是使用赋值运算符。
StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) {
    builder = new StringBuilder("ipad");
}
foo(sb); // sb 没有被改变,还是 "iphone"。

重点理解为什么,第三个例子和第四个例子结果不同?

下面是第三个例子的图解:

下面是第四个例子的图解:


根据Horstmann的《java核心技术》(中文第8版P115-P117)的描述,java中是没有引用传递的,原文摘录如下:
“java程序设计语言总是采用值调用。也就是说,方法得到的是所有参数值的一个拷贝,特别是,方法不能修改传递给它的任何参数变量的内容(若是对象最多改变对象的变量)。”

“有些程序员(甚至是本书的作者),认为java程序设计语言对对象采用的是引用调用,实际上这种理解是不对的。”

总结起来,java中参数传递情况如下: (针对方法中传入的参数而言)
· 一个方法不能修改一个基本数据类型的参数 
· 一个方法可以修改一个对象参数的状态 
· 一个方法不能实现让对象参数引用一个新对象

eg:

下面使用《java核心技术》的一段代码解释为什么java中不存在引用传递:编写一个交换对象的方法:

Employee a=new Employee("tom", 7000);
Employee b=new Employee("jerry", 4000);

public static void swap(Employee x,Employee y){
    //交换两个员工的姓名
    Employee temp=x;
    x=y;
    y=temp;
}

如果java使用的是引用传递,那么swap方法应该可以实现交换两个对象值的效果,然而最终结果是,swap并没有改变存储在a和b中的对象引用。swap方法的参数x,y被初始化为两个对象引用值的拷贝,这个方法交换的是两个拷贝,最终没有实现交换的结果。



展开阅读全文

没有更多推荐了,返回首页