开篇之前先说结论:java只有值传递!
1. java的两种数据类型的传递类型
1.1 基本类型
基本类型有8种包括:int,short,long,char,float,double,boolean,byte
例1:int a = 234;
1,在栈内存中的下一个空的地址如:126。
2,在这个地址上放置一个int变量值为234。
这个时候a=234,而不是126。所以对于基本类型是值传递!
1.2 引用类型
引用类型包括:类类型,接口类型,数组和对象
例2:User user = new User(“小明”, 3, 56);
1,在堆内存中找到一个空的地址如:12306。
2,在堆内存中根据传入的参数创建user对象。
3,在栈内存中找到一个空的地址如:126。
4,把堆内存的地址12306放置到栈内存地址为126的位置上。
这时候如果你直接System.out.println(user);出来的是user对象在堆内存中的地址(12306),这个时候很多人就会觉得我拿到的是地址,那不就是引用传递了吗?
但我们要先清楚的一点是,引用传递和值传递是相对什么来说,那就是相对于我们直接操作的内存来说的,而在java里面并没有什么方法让你可以直接操作堆内存,为了我们写的程序的安全性设计者只让我们操作栈内存。
相对于栈内存来说126是地址,12306是值(这个值是堆内存的地址),所以说引用类型也是值传递的。
2. 证明java是值传递?
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
change(list);
System.out.println(list);
}
public static void change(List<Integer> list) {
list = new ArrayList<>();
list.add(100);
}
通过上面的讲解相信大家知道这个结果是多少。
那么为什么是1呢,明明在方法里重新赋值了,下面我画一下执行这几个语句时的内存是怎么变化的。
有一个比较方便的方法帮大家区分引用传递,无论是什么编程语言
存放数据的地方与你的调用是否有一个中介,例如java的中介就是栈内存,我们都是通过栈内存中的值再去找堆内存。这就导致无法直接操作内存地址,因此我们所有对引用(栈内存中的变量)的重新赋值并不会影响到其他引用,这也是java相对于c语言比较安全但没这么灵活的原因。
如果有说的不好,请大家多多指教