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


引言


我们先给本文定下基调,java是值传递


有一种说法,引用传递实际上也就是值传递。这个说法很有意思,实际上这种说法也是有道理的,传递引用,这个引用实际上就是一个地址,也即是一个值。


什么是值传递和引用传递


首先,不要纠结于 Pass By Value 和 Pass By Reference 的字面上的意义,否则很容易陷入所谓的“一切传引用其实本质上是传值”这种并不能解决问题无意义论战中。更何况,要想知道Java到底是传值还是传引用,起码你要先知道传值和传引用含义。


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


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

QQ截图20170926153341.png

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


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


num = 20;
str = "java";

QQ截图20170926153341.png

对于基本类型 num ,赋值运算符会直接改变变量的值,原来的值被覆盖掉。
对于引用类型 str,赋值运算符会改变引用中所保存的地址,原来的地址被覆盖掉。但是原来的对象不会被改变(重要)。


例子


参数传递基本上就是赋值操作


第一个例子:基本类型
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"。

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


QQ截图20170926153341.png

QQ截图20170926153341.png


例子5


public class Employee {
public int age;
}
public class Main {
public static void changeEmployee(Employee employee3)
{
employee3 = new Employee(); // flag 1
employee3.age = 1000;
}
public static void main(String[] args) {
Employee employee = new Employee();
employee.age = 100;
changeEmployee(employee);
System.out.println(employee.age);
}
}
输出: 100
如果把 flag 1 位置代码注释,那么程序结果输出1000
---原因同上

总结


  • = 号的理解是最重要的,他是一个动词,可能会引起左边变量值的改变

  • java中方法参数传递方式是按值传递。

  • 如果参数是基本类型,传递的是基本类型的字面量值的拷贝。也就是你我没有半毛钱关系
  • 如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝。你我可能存在关系

  1. = 是赋值操作(任何包含=的如+=、-=、 /=等等,都内含了赋值操作)。不再是你以前理解的数学含义了,而+ - /和 = 在java中更不是一个级别,换句话说, = 是一个动作,一个可以改变内存状态的操作,一个可以改变变量的符号,而+ - /却不会。这里的赋值操作其实是包含了两个意思:1、放弃了原有的值或引用;2、得到了 = 右侧变量的值或引用。Java中对 = 的理解很重要啊!!可惜好多人忽略了,或者理解了却没深思过。

  2. 对于基本数据类型变量,= 操作是完整地复制了变量的值。换句话说,“=之后,你我已无关联”;至于基本数据类型,就不在这科普了。

  3. 对于非基本数据类型变量,= 操作是复制了变量的引用。换句话说,“嘿,= 左侧的变量,你丫别给我瞎动!咱俩现在是一根绳上的蚂蚱,除非你再被 = 一次放弃现有的引用!!上面说了 = 是一个动作,所以我把 = 当作动词用啦!!”。而非基本数据类型变量你基本上可以参数本身是变量

  4. 参数传递本质就是一种 = 操作。参数是变量,所有我们对变量的操作、变量能有的行为,参数都有。所以把C语言里参数是传值啊、传指针啊的那套理论全忘掉,参数传递就是 = 操作。

如果你感觉文章对你又些许感悟,你可以支持我!!
-------------本文结束感谢您的阅读-------------