相信很多朋友在以往的Java学习过程中,一直对Java参数传递的到底是值还是引用有些模糊,希望通过这篇文章能让大家明白Java的参数传递到底是怎样的。
我们先来看下 thinking in java 一书中对Java参数传递给出的经典解释:
When you are passing primitives into a method,you get a distinct copy of the primitive.When you are passing a reference into a method ,you get a copy of the reference.(如果Java是传值,那么传递的是值的副本;如果Java是传引用,那么传递的是引用的副本)
在Java中变量分为两种:
①对于基本数据类型(byte、short、int、long、double、float、boolean、char) Java传递的是值的副本。
②对于引用数据类型,Java传递的都是引用的副本(传引用副本的本质就是复制指向地址的指针)。
对于基本数据类型来讲,传值就是把自己复制一份传递,即使自己的副本变了,自己也不变。对于引用数据类型,它传递的是引用的副本指向自己的地址。
我们先来看基本数据类型:
public static void func1(int x){
x=10;
}
public static void main(String[] args) {
int x = 20;
func1(x);
System.out.println(x);
}
程序最后输出的结果是多少?
来画个图分析下
int x = 20;
开始定义了一个局部变量x = 20
func1(x);
执行func1 方法,在栈中复制了一个副本。一个局部变量。
System.out.println(x);
执行完func1 方法后,栈中的局部变量x=10 被垃圾收集器回收。最后输出的结果是20。
我们再来看引用数据类型:
class Cat{
int age=10;
}
public static void func2(Cat c){
c.age=10;
}
public static void main(String[] args) {
Cat c = new Cat();
c.age = 5;
func2(c);
System.out.println(c.age);
}
结果输出是多少?
我们再来画个图
Cat c = new Cat();
c.age = 5;
在堆中创建一个cat对象 age属性为5
func2(c);
System.out.println(c.age);
由于传递的引用地址,func2 直接找到了堆中真正的cat对象并修改了它的age属性为10
最终输出结果为10。