Java中的cloneable接口

学习Java语言程序设计时,接口一章提到cloneable,又联想到关于对象的复制相关问题,于是就把两者结合在一起,进行一个简单的辨析。

class Employee implements Cloneable{
    String name;
    int id;

    Address address;
    public Employee(String name,int id,Address address){
        this.name=name;
        this.id=id;
        this.address=address;
    }

    public void setId(int id) {
        this.id = id;
    }

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

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", address=" + address +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        
        return super.clone();
    }
}

 在Employee类中定义了String类型的name,int类型的id,和一个引用数据类型型Address类的address对象。还声明了getter,setter方法来对Employee对象的属性进行修改。


class myAddress implements Cloneable{
    String streetName;
    int streetId;
    public myAddress(String streetName,int streetId){
        this.streetName=streetName;
        this.streetId=streetId;
    }

    public void setStreetId(int streetId) {
        this.streetId = streetId;
    }


    public void setStreetName(String streetName) {
        this.streetName = streetName;
    }

  
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

 在该Address类中实现了对于String类型的streetName和int类型的streetId的定义,达到后续对于属性修改的目的。

public class _demo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Employee e1=new Employee("aaa",12,new Address(111,"aaaaa"));
        System.out.println(e1);
        Employee e2=e1;
        System.out.println(e2);
        e2.setId(11);
        e2.setName("bbb");
        e2.getAddress().setStreetid(112);
        e2.getAddress().setStreetname("bbbbb");
        System.out.println(e1);
        System.out.println(e2);


        Employee e22=(Employee) e1.clone();
        System.out.println(e22);
        e22.setId(10);
        e22.setName("ccc");
        e22.getAddress().setStreetid(132);
        e22.getAddress().setStreetname("ccccc");
        System.out.println(e1);
        System.out.println(e2);
        System.out.println(e22);
}

在主函数中声明了一个引用e1,其指向一个这样的对象,其属性值分别为(按照name,id,streetName,streetId的顺序) aaa,12,aaaaaa,111。

之后声明另一个引用e2,和e1指向堆中的同一个对象。如果在e2中调用Empoyee类中的setter,getter函数对属性值进行修改,此时打印出e1,e2,会发现两者的属性值同步改变,即属性值都变成e2修改后的值--bbb,11,bbbbb,112。因为e2中拿到的是e1引用所指向的地址,直接对堆中的对象进行修改,结果就是从e1,e2拿到的都是修改后的对象。

但是再声明一个e22引用,其不同之处在于e22是由e1通过Cloneable中的clone复制得到的,对与基本数据类型,e1直接是把属性对应的数值拷贝给e22;对于引用数据类型,则只是把地址拷贝给e22,此时就会出现e1,e2,e22中的拿到的其实是堆中的同一个地址对象。此时如果e22对name,id属性改变,只是会改变自身的这些属性值 ,对于e1,e2的值不会产生改变。但是若是堆address属性改变,就会造成三者的属性同时发生改变。

对应的main函数中的输出如下:

//        Employee{name='aaa', id=12, address=Address{streetid=111, streetname='aaaaa'}}
//        Employee{name='aaa', id=12, address=Address{streetid=111, streetname='aaaaa'}}
//        Employee{name='bbb', id=11, address=Address{streetid=112, streetname='bbbbb'}}
//        Employee{name='bbb', id=11, address=Address{streetid=112, streetname='bbbbb'}}
//        Employee{name='bbb', id=11, address=Address{streetid=112, streetname='bbbbb'}}
//        Employee{name='bbb', id=11, address=Address{streetid=132, streetname='ccccc'}}
//        Employee{name='bbb', id=11, address=Address{streetid=132, streetname='ccccc'}}
//        Employee{name='ccc', id=10, address=Address{streetid=132, streetname='ccccc'}}

如有错误,欢迎指正!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值