看了很多关于Java中的值传递和引用传递,我觉得有所收获,但是还是觉得有些迷惑,下面是关于我自己对于Java中的值传递和引用传递的理解。【作为一个Java初学者的理解,下面的文章可能不对,请谨慎甄别和选择,也欢迎大家来提出意见】
众所周知,Java中的数据类型分为两大类:基本数据类型和引用数据类型,在这里就不列举分别有哪些了。
比如我们定义一个基本数据类型:
int x = 10;
x = 100;
这里第一行的x
表示的是一块内存,其大小为4个字节,存储的是int
类型的数据,不妨设这块内存的起始地址为0x1111
,这块内存中的值是10
。更为形象的说,可以将x
视为起始地址为0x1111
的这块内存。
第二行代码就可以看出x = 100
,而其具体是怎么做到的呢?就是将100
这个值赋值到名为x
的这块内存中,也就是赋值到0x1111
这块内存上。
我们定义一个引用数据类型
public static void main(String[] args) {
Person p1 = new Person("Alice", 10);
p1 = new Person("Bob", 20);
}
class Person {
int age;
String name;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
main
方法中,一开始的p1
是在内存中申请了一块内存,其大小为一个Person
类的大小,存储的是Person
类型的数据,内容有Alice, 10
等信息,这块内存的起始地址不妨假设为0x2222
。那么其实和基本数据类型一样的是,p1
的含义就是这个已经实例化的对象的起始地址,也就是p1
就是0x2222
的这块内存。
紧接着p1 = new Person("Bob", 20);
,这就是再次申请了一块内存,而这块内存中存储的就是Bob, 20
等信息,假设这块内存的起始地址是0x3333
,然后将p1
的含义改为0x3333
,也就是说p1
变为了0x3333
的这块内存。
当然,真正的JVM处理可能并不会将p1
直接改为地址,也许是其他的操作,但是其本质上的意思就是上面的情况。
相同点:
不同点:
接着分析传参的问题。
Java中传递的参数有两种数据类型,一种是基本数据类型,另一种就是引用数据类型。因此就有两种传参规则:
具体来说什么是值传递,什么是引用传递。
这也就是为什么有些人会说,在Java中其实并没有引用传递,都是值传递的原因,其实他们说的也是对的,因为本质上来说都是值传递,只不过一个是数据本身的值传递,另一个是数据的地址的值传递而已。
在这里就不详细介绍值传递的问题了,直接说引用传递。
上一节说的引用传递可能描述的并不是很好理解,举个例子来说:
public static void main(String[] args) {
Person p1 = new Person("Alice", 10);
System.out.println(p1);
Person.change1(p1);
System.out.println(p1);
Person.change2(p1);
System.out.println(p1);
}
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public static void change1(Person p) {
p = new Person("Bob", 20);
}
public static void change2(Person p) {
p.age = 70;
}
}
从上面代码进行分析:
change1
和change2
传进来的都是Person
类,都是属于引用传递,那么为什么change1
没有影响main
函数中的p1
,而change2
却改变了main
函数中的p1
呢?
根据Java的引用传递规则来看:
change1
:传进来的形参p
是Alice, 10
这样的内存的地址的值0x4444
,而直接对p = new Person("Bob", 20);
这样的操作,只是将形参p
的值改为了Bob, 20
这样的内存的地址的值0x5555
,由于Java的引用传递的规则来看,这并不会影响mian
中的p1
的值还是等于0x4444
;change2
:传进来的形参p
是Alice, 10
这样的内存的地址的值0x4444
,紧接着,对0x4444
这块内存中的age
部分内存进行了修改,而这块内存也还是在main
中的p1
所对应的内存中,因此,会对main
中的p1
进行影响。值传递和引用传递其本身都是对值的复制,不同的是,一个是数据本身的值复制,一个是数据的地址的值复制。