浅拷贝,使用setter方法修改了基本数据类型的内存地址

来源:9-2 原型模式coding

AndrewLu

2020-12-16

在需要拷贝的类中声明了个int类型的变量(考虑到Integer类型是被final修饰默认创建新的对象),从结果中看出clone方法默认为浅拷贝,但是我发现通过age的setter方法修改值后,stu1和stu3(拷贝)的age内存地址不一样了,所以我很困惑基本数据类型的setter方法还会修改内存地址吗???

public class CopyTest {

    public static void main(String []args) throws CloneNotSupportedException {
        Student stu1 = new Student("Andrew",23);
        //把stu1拷贝给stu3
        Student stu3 = (Student) stu1.clone();

        //比较拷贝完后的stu1和stu3中的age地址: 输出true,表示stu3为浅拷贝
        System.out.println(stu1.getAge()== stu3.getAge());

        //修改stu1的age值
        stu1.setAge(24);


       //比较原对象和拷贝对象的age值和地址,如果是浅拷贝那么里面的属性是共享同一个内存地址,那么修改stu1之后stu2会随之改变
        //输出24,改变了
        System.out.println("stu1:"+stu1.getAge());
        //输出23,没变,??
        System.out.println("stu3:"+stu3.getAge());
        //输出false,表明不是一个内存地址,??
        System.out.println("比较age地址:"+(stu3.getAge()==stu1.getAge()));
    }

}

class Student implements Cloneable{

    private String name;
    private int age;

    Student(String name,int age){
        this.name = name;
        this.age = age;
    }

    public String getName(){
        return this.name;
    }

    public int getAge(){
        return this.age;
    }

    public void setName(String name){
        this.name = name;
    }

    public void setAge(int age){
        this.age = age;
    }

//没有改写,使用默认的clone方法
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
写回答

1回答

杰9407987

2020-12-16

你上面也说了,你用的是基本数据类型int,所以不存在对象引用,这些基本类型数据是存在运行时常量池的,并不是通过new来的,所以你修改基本数据类型,都是深拷贝,深、浅拷贝,只是针对引用类型对象。比如new Object(),new Date()这些是存在堆内存(heap)中。这里涉及到jvm的内存分配知识,个人理解,有不正确的还望各位大佬更正。再补充一张内存模型图,基本数据类型就是存在方法区里面的运行时常量池中,也称作“非堆”,

//img.mukewang.com/szimg/5fd9a7780816e19d04420330.jpg

1
1
AndrewLu
非常感谢!
2020-12-16
共1条回复

Java设计模式精讲-Debug方式+内存分析

系统学习设计原则,设计模式,锤炼编码内功,赢取高薪Offer

3430 学习 · 407 问题

查看课程