• admin
  • 440
  • 2025-07-03 15:53:54

首先给大家解释一下这几个名词的概念:

值传递:在方法的调用过程中,实参把它的实际值传递给形参,此传递过程就是将实参的值复制一份传递到函数中,这样如果在函数中对该值(形参的值)进行了操作将不会影响实参的值。因为是直接复制,所以这种方式在传递大量数据时,运行效率会特别低下。

引用传递:引用传递弥补了值传递的不足,如果传递的数据量很大,直接复过去的话,会占用大量的内存空间,而引用传递就是将对象的地址值传递过去,函数接收的是原始值的首地址值。在方法的执行过程中,形参和实参的内容相同,指向同一块内存地址,也就是说操作的其实都是源数据,所以方法的执行将会影响到实际对象。

浅拷贝:java中提供的clone方法就是浅拷贝,浅拷贝会拷贝一个对象

深拷贝:之所以有深浅之分,是因为浅拷贝在拷贝一个对象的时候,不会拷贝对象的子类,所以引入了深拷贝的概念,解决这个问题就可以让被拷贝的子类实现clone接口,就可以实现深拷贝。

应用场景

值传递:

值传递传递的是真实内容的一个副本,对副本的操作不影响原内容,也就是形参怎么变化,不会影响实参对应的内容。

public class Test

{

public static void changeStr(String str)

{

str = "welcome";

}

public static void main(String[] args)

{

String str = "1234";

changeStr(str);

System.out.println(str);

}

}

引用传递:

引用 也就是指向真实内容的地址值,在方法调用时,实参的地址通过方法调用被传递给相应的形参,在方法体内,形参和实参指向通愉快内存地址,对形参的操作会影响的真实内容。对象没有被拷贝,拷贝的是栈地址(地址、指针)

public class Demo {

public static void PersonCrossTest(Person person){

System.out.println(“传入的person的name:”+person.getName());

person.setName(“二哈”);

System.out.println("方法内重新赋值后的name:"+person.getName());

}

//测试

public static void main(String[] args) {

Person p=new Person();

p.setName("藏獒");

p.setAge(3);

PersonCrossTest(p);

System.out.println("方法执行后的name:"+p.getName());

}

我们通过代码展示一下深浅拷贝:

package com.yaolong.clone;

public class Person implements Cloneable{

//private Integer age;

private int age;

private String name;

public Person(Integer age, String name) {

super();

this.age = age;

this.name = name;

}

public Integer getAge() {

return age;

}

public void setAge(Integer age) {

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

@Override

public String toString() {

return super.toString();

}

@Override

protected Object clone() throws CloneNotSupportedException {

return super.clone();

}

}

//对象拷贝

private static void copyRealObject() throws CloneNotSupportedException{

Person p = new Person(23, "zhang");

Person p1 = (Person) p.clone();

System.out.println(p);

System.out.println(p1);

}

可以看出,二者的对象地址不一样,因此实现了拷贝。

但是还是有个问题,就是Person类中有一个String类型的引用对象name,它真的也被拷贝过去了吗,还是说依然

是引用的是同一个name对象呢,在上面的代码基础上,我们继续打印:

System.out.println("pName:"+p.getName().hashCode());

System.out.println("p1Name:"+p1.getName().hashCode());

可见,二者的name属性依然是指向同一个对象。上面故意将age属性改为int基本类型,因为基本数据类型是不存在引用问题。这实际上就是典型的浅拷贝。

深拷贝:

public class DeepCopy {

public static void main(String[] args) throws CloneNotSupportedException {

Teacher teacher = new Teacher();

teacher.setName("riemann");

teacher.setAge(28);

Student student1 = new Student();

student1.setName("edgar");

student1.setAge(18);

student1.setTeacher(teacher);

Student student2 = (Student) student1.clone();

System.out.println("-------------拷贝后-------------");

System.out.println(student2.getName());

System.out.println(student2.getAge());

System.out.println(student2.getTeacher().getName());

System.out.println(student2.getTeacher().getAge());

System.out.println("-------------修改老师的信息后-------------");

// 修改老师的信息

teacher.setName("jack");

System.out.println("student1的teacher为: " + student1.getTeacher().getName());

System.out.println("student2的teacher为: " + student2.getTeacher().getName());

}

}

class Teacher implements Cloneable {

private String name;

private int age;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public Object clone() throws CloneNotSupportedException {

return super.clone();

}

}

class Student implements Cloneable {

private String name;

private int age;

private Teacher teacher;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public Teacher getTeacher() {

return teacher;

}

public void setTeacher(Teacher teacher) {

this.teacher = teacher;

}

public Object clone() throws CloneNotSupportedException {

// 浅复制时:

// Object object = super.clone();

// return object;

// 改为深复制:

Student student = (Student) super.clone();

// 本来是浅复制,现在将Teacher对象复制一份并重新set进来

student.setTeacher((Teacher) student.getTeacher().clone());

return student;

}

}

运行结果:

-------------拷贝后-------------

edgar

18

riemann

28

-------------修改老师的信息后-------------

student1的teacher为: jack

student2的teacher为: riemann