一、什么是值传递、什么是引用传递?
1.概念介绍
值传递:实参把值传递给形参。
引用传递:实际参数传给形参堆内存的引用地址
区别:所以引用传递实际上指向的是用一块区域,对形参的修改会影响到实参,而值传递的形参与实参在内存上是两个独立的变量,一方修改互不影响。
2.代码演示
1.值传递
public class Father {
int age;
public void setAge(int x){
x=100;
}
public static void main(String[] args) {
Father fat=new Father();
fat.age=32;
fat.setAge(fat.age);
System.out.println(fat.age);
}
}
输出结果:
32
Process finished with exit code 0
在setAge函数中,age作为实参把值(32)传给了形参x,然后改变形参x的值(x=100),可以看到并不影响实参age的值.
2.引用传递
public class Father {
public void changeVlaue(int [] x){
x[2]=100;
}
public static void main(String[] args) {
Father fat =new Father();
int [] array={0,1,2,3,4};
for(int temp:array){
System.out.print(temp+" ");
}
System.out.println();
fat.changeVlaue(array);
for(int temp:array){
System.out.print(temp+" ");
}
}
}
运行结果:
0 1 2 3 4
0 1 100 3 4
Process finished with exit code 0
这个changeVlaue中我们可以看到,我们把array的首地址传给x了,所以当对数组x做改变的时候,原来的array也发生了改变.(实际上我们也经常这样做,把一个数组的首地址当作形参传入某个函数,对这个数组进行排序等操作,其实这个就是引用传递)
3.总结
JAVA里面的数据类型,如图
所以我们可以下结论:
形参为基本类型数据都是值传递(只是在拷贝它的值),
而形参是引用数据类型的都是引用传递(只是对对象的引用,实际上指的是同一个对象).
(当然C++里面 int & x,也可以做到引用传递,又当然String这个东西是值传递)
二、什么是深拷贝、什么是浅拷贝?
在我们了解值传递与引用传递的基础上,我们可以更好的了解深拷贝与浅拷贝
1.概念介绍
浅拷贝:只是对基本数据进行了拷贝,而对引用类型进行了引用传递.
深拷贝:只是对基本数据进行了拷贝,而对引用类型进行了拷贝的时候,是创建了一个新的对象并拷贝.
区别:很明显,两者对基本数据类型的处理都是值传递,而对引用类型数据,前者直接引用,后者是开辟新的空间,并赋值,所以我们回到深拷贝的目的,改变形参不影响实参,两者的区别根本在于创建新的空间。
2.代码介绍
(1)我们先看类中只有基本数据类型的代码
package test;
/**
* @author gsw
*/
public class Father {
int age;
Father(int x) {
this.age = x;
}
Father(Father temp) {
this(temp.age);
}
public static void main(String[] args) {
//fat2没有创建了新的空间,而fat3创建了新的空间
Father fat1 = new Father(32);
Father fat2 = fat1;
Father fat3 = new Father(fat1);
System.out.println(fat1+" "+fat1.age);
System.out.println(fat2+" "+fat2.age);
System.out.println(fat3+" "+fat3.age);
fat1.age=300;
System.out.println("改变值之后:");
System.out.println(fat1+" "+fat1.age);
System.out.println(fat2+" "+fat2.age);
System.out.println(fat3+" "+fat3.age);
}
}
运行结果:
test.Father@133314b 32
test.Father@133314b 32
test.Father@b1bc7ed 32
改变值之后:
test.Father@133314b 100
test.Father@133314b 100
test.Father@b1bc7ed 32
我们一步一步分析
(i)构造函数
Father(int x) {
this.age = x;
}
Father(Father temp) {
this(temp.age);
}
很明显这个复制构造函数本质上是调用有形参的构造函数(值传递),而且Father这个类里面只有一个成员变量那就是int age ,一个基本数据类型.所以这样的复制也一定都是浅复制,因为类里面只涉及基本数据类型。
(ii)main函数代码
fat2的地址与fat1指向的地址一样,而fat3与fat1指向的地址不一样。所以改变fat1.age的时候,fat2随之改变而fat3没有。可以看到fat2没有创建了新的空间,而fat3用new创建了新的空间,所以尽管两者调用的构造函数都是浅拷贝(值传递),但是fat3却达到了深拷贝的目的。
(2)我们再看类中有基本数据类型与引用类型的代码
package test;
/**
* @author GT
*/
public class GrandFather {
int head;
GrandFather (int x){
head=x;
}
GrandFather (){
head=0;
}
}
package test;
/**
* @author gsw
*/
public class Father {
int age;
GrandFather grandFather=new GrandFather();
Father(int head,int x) {
grandFather.head=head;
this.age = x;
}
Father(Father temp) {
this(temp.grandFather.head,temp.age);
}
public static void main(String[] args) {
Father fat1 = new Father(1,32);
Father fat2 = fat1;
Father fat3 = new Father(fat1);
System.out.println(fat1+" "+fat1.age+" "+fat1.grandFather+" head:"+fat1.grandFather.head);
System.out.println(fat1+" "+fat2.age+" "+fat2.grandFather+" head:"+fat2.grandFather.head);
System.out.println(fat3+" "+fat3.age+" "+fat3.grandFather+" head:"+fat3.grandFather.head);
fat1.age=300;
fat1.grandFather.head=2;
System.out.println("改变值之后:");
System.out.println(fat1+" "+fat1.age+" "+fat1.grandFather+" head:"+fat1.grandFather.head);
System.out.println(fat1+" "+fat2.age+" "+fat2.grandFather+" head:"+fat2.grandFather.head);
System.out.println(fat3+" "+fat3.age+" "+fat3.grandFather+" head:"+fat3.grandFather.head);
}
}
test.Father@cc34f4d 32 test.GrandFather@17a7cec2 head:1
test.Father@cc34f4d 32 test.GrandFather@17a7cec2 head:1
test.Father@65b3120a 32 test.GrandFather@6f539caf head:1
改变值之后:
test.Father@cc34f4d 300 test.GrandFather@17a7cec2 head:2
test.Father@cc34f4d 300 test.GrandFather@17a7cec2 head:2
test.Father@65b3120a 32 test.GrandFather@6f539caf head:1
我们在Father类中,增加了一个GrandFather类型的成员,至此Father里面有基本数据类型成员变量与引用类型数据成员变量,同样的,fat1与fat2的中的引用数据类型的类的地址还是一样的,说明fat2还是对fa1的整个引用。

那fat3为什么可以实现深复制
Father fat1 = new Father(1,32);
Father fat2 = fat1;
Father fat3 = new Father(fat1);
之前讲过类本来就是引用类型,这家伙你不给它开辟内存空间,复制就都是引用。所以,不管类里面套娃了多少类或者其余的引用类型,只要给每一个类开辟了空间,那就属于深复制。
到这里,差不多讲完了,但是我总感觉有地方不严谨,没有研究透彻,本文将持续更新,欢迎读者指正、交流。
此文给我很大的启示,讲的是clone方法的深、浅复制,点此进入 https://www.html.cn/qa/other/22850.html

本文详细介绍了值传递和引用传递的概念,并通过Java代码示例展示了它们的区别。值传递是基本类型数据的拷贝,而引用传递则是对象的引用。接着,文章阐述了深拷贝和浅拷贝,指出浅拷贝仅拷贝基本数据,而深拷贝会创建新对象。通过实例分析,展示了如何在Java中实现深拷贝和浅拷贝的效果。
979

被折叠的 条评论
为什么被折叠?



