假克隆、浅克隆、深克隆、序列化、以及深克隆和序列化的效率

一、假克隆

1、假克隆是 直接给地址

2、上代码

(1)员工类 Employee:有name、age两个属性,并重写toString()

    1

    2

    3

    4

    5

    6

    7

    8

    9

   10

   11

   12

public class Employee {

        //员工的name

        private String name;

        //员工的age

        private int age;

        

        //省略getset方法

        @Override

        public String toString() {

                return "姓名:" + name + ",年龄:" + age;

        }

}

(2)测试类 Test

    1

    2

    3

    4

    5

    6

    7

    8

    9

   10

   11

   12

   13

   14

   15

   16

   17

   18

   19

   20

   21

public class Test {

        public static void main(String[] args) {

                System.out.println("克隆前:");

                Employee employee = new Employee();

                employee.setName("张三");

                employee.setAge(20);

                System.out.println(employee.toString());

                

                System.out.println("克隆后:");

                Employee employee2 = employee;

                employee2.setName("李四");

                employee2.setAge(22);

                System.out.println("employee:"+employee);

                System.out.println("employee2:"+employee2);

                

                System.out.println("___________________________________");

                System.out.println("x.clone() != x  --->" + (employee != employee2));

                System.out.println("x.clone().getClass() == x.getClass() -->"+(employee.getClass() == employee2.getClass()));

                System.out.println("x.clone().equals(x) --->" + employee.equals(employee2));

        }

}

(3)运行结果:

 

 

二、浅克隆

1、浅克隆 通过Cloneable 的 clone 方法实现克隆

2、特点:

(1)如果对象成员是基本类型,浅克隆即可完成,如果对象的成员变量包含

引用类型,就会直接复制对象地址

(2)当然如果引用类型是不可变的,如String类型,则可以

3、上代码:

(1)员工类 Employee:有name、age、Address 三个属性,其中

Address 是引用类型,并重写toString(),实现 clone 方法

    1

    2

    3

    4

    5

    6

    7

    8

    9

   10

   11

   12

   13

   14

   15

   16

   17

   18

   19

   20

   21

   22

   23

   24

   25

   26

   27

   28

public class Employee implements Cloneable {

        //员工的name

        private String name;

        //员工的age

        private int age;

        //地址

        private Address address;

        

        public Employee(String name, int age, Address address) {

                super();

                this.name = name;

                this.age = age;

                this.address = address;

        }

        

        //省略getset方法

        

        @Override

        public String toString() {

        return "姓名:" + name + ",年龄:" + age + ",地址:" + address;

        }

        

        //clone实现克隆

        @Override

        protected Employee clone() throws CloneNotSupportedException {

                return (Employee) super.clone();

        }

}

(2)地址类 Address ,有国家、省、城市 三个属性

    1

    2

    3

    4

    5

    6

    7

    8

    9

   10

   11

   12

   13

   14

   15

   16

   17

   18

public class Address {

        private String state;

        private String province;

        private String city;

        

        public Address(String state, String province, String city) {

                super();

                this.state = state;

                this.province = province;

                this.city = city;

        }

        //省略getset

        @Override

        public String toString() {

                return "Address [state=" + state + ", province=" + province + ", city=" + city + "]";

        }

 

}

(3)测试类 Test

    1

    2

    3

    4

    5

    6

    7

    8

    9

   10

   11

   12

   13

   14

   15

   16

   17

   18

   19

   20

   21

   22

   23

public class Test {

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

                System.out.println("克隆前:");

                Address address = new Address("中国", "吉林", "长春");

                Employee employee = new Employee("张三", 30, address);

                System.out.println(employee.toString());

                

                System.out.println("克隆后:");

                Employee employee2 = employee.clone();

                employee2.setName("李四");

                employee2.setAge(22);

                employee2.getAddress().setState("中国");

                employee2.getAddress().setProvince("四川");

                employee2.getAddress().setCity("成都");

                System.out.println("employee:" + employee);

                System.out.println("employee2:" + employee2);

                

                System.out.println("___________________________________");

                System.out.println("x.clone() != x  --->" + (employee != employee2));

                System.out.println("x.clone().getClass() == x.getClass() -->"+(employee.getClass() == employee2.getClass()));

                System.out.println("x.clone().equals(x) --->" + employee.equals(employee2));

        }

}

(4)运行结果:

 

(5)关于 Cloneable 的 clone(),Cloneable接口是一个空的标志接口,其

实现是调用 Object 的 clone(),因为这是一个 native 方法,怎么实现不清楚,源码如下:

    1

    2

    3

    4

    5

    6

    7

* Creates and returns a copy of this object.  The precise meaning

* of "copy" may depend on the class of the object. The general

* intent is that, for any object {@code x}, the expression:

* x.clone() != x     will be true,

* x.clone().getClass() == x.getClass()     will be {@code true},

* x.clone().equals(x)      will be {@code true},

protected native Object clone() throws CloneNotSupportedException;

 

三、深克隆

1、通过对可变引用类型实现 Cloneable 的 clone()方法

2、如果引用类型中还有可变的引用类型成员变量,则它也要进行克隆

3、如果类的成员变量比较复杂,例如使用了多个可变引用类型,使用 clone() 方

法来克隆是非常麻烦的。

4、代码实现:

(1)员工类 Employee:有name、age、Address 三个属性,其中

Address 是引用类型,并重写toString(),实现 clone 方法

    1

    2

    3

    4

    5

    6

    7

    8

    9

   10

   11

   12

   13

   14

   15

   16

   17

   18

   19

   20

   21

   22

   23

   24

   25

   26

   27

   28

public class Employee implements Cloneable {

        //员工的name

        private String name;

        //员工的age

        private int age;

        //地址

        private Address address;

        

        public Employee(String name, int age, Address address) {

                super();

                this.name = name;

                this.age = age;

                this.address = address;

        }

        //省略,,,,

        @Override

        public String toString() {

                return "姓名:" + name + ",年龄:" + age + ",地址:" + address;

        }

        

        //实现浅克隆

        @Override

                protected Employee clone() throws CloneNotSupportedException {

                Employee employee = (Employee) super.clone();

                employee.address = address.clone();

                return employee;

        }

}

(2)地址类 Address ,有国家、省、城市 三个属性,并实现 clone()

    1

    2

    3

    4

    5

    6

    7

    8

    9

   10

   11

   12

   13

   14

   15

   16

   17

   18

   19

   20

   21

   22

   23

   24

public class Address implements Cloneable {

        private String state;

        private String province;

        private String city;

 

        public Address(String state, String province, String city) {

                super();

                this.state = state;

                this.province = province;

                this.city = city;

        }

        //。。。。。

        @Override

        protected Address clone() throws CloneNotSupportedException {

                return (Address) super.clone();

        }

        

        @Override

        public String toString() {

                return "Address [state=" + state + ", province=" + province + ", city=" + city + "]";

        }

}

(3)测试类 Test

    1

    2

    3

    4

    5

    6

    7

    8

    9

   10

   11

   12

   13

   14

   15

   16

   17

   18

   19

   20

   21

   22

   23

public class Test {

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

                System.out.println("克隆前:");

                Address address = new Address("中国", "吉林", "长春");

                Employee employee = new Employee("张三", 30, address);

                System.out.println(employee.toString());

                

                System.out.println("克隆后:");

                Employee employee2 = employee.clone();

                employee2.setName("李四");

                employee2.setAge(22);

                employee2.getAddress().setState("中国");

                employee2.getAddress().setProvince("四川");

                employee2.getAddress().setCity("成都");

                System.out.println("employee:" + employee);

                System.out.println("employee2:" + employee2);

                

                System.out.println("___________________________________");

                System.out.println("x.clone() != x  --->" + (employee != employee2));

                System.out.println("x.clone().getClass() == x.getClass() -->"+(employee.getClass() == employee2.getClass()));

                System.out.println("x.clone().equals(x) --->" + employee.equals(employee2));

        }

}

(4)测试结果

 

四、序列化

1、通过实现Serializable接口,该接口没有定义任何方法,是一个标志接口

2、如果类中有引用类型成员变量,则该变量也需要实现 Serializable 接口,依次类

推,当然序列化到本地和内存都可以

3、代码实现:

(1)Employee 还是员工类,实现Serializable接口

    1

    2

    3

    4

    5

    6

    7

    8

    9

   10

   11

   12

   13

   14

   15

   16

   17

   18

   19

   20

   21

public class Employee implements Serializable {

        private static final long serialVersionUID = 1L;

        //员工的name

        private String name;

        //员工的age

        private int age;

        //地址

        private Address address;

        

        public Employee(String name, int age, Address address) {

        super();

        this.name = name;

        this.age = age;

        this.address = address;

        }

        //省略,,,,

        @Override

        public String toString() {

                return "姓名:" + name + ",年龄:" + age + ",地址:" + address;

        }

}

(2)Address 还是地址类,实现Serializable接口

    1

    2

    3

    4

    5

    6

    7

    8

    9

   10

   11

   12

   13

   14

   15

   16

   17

   18

public class Address implements Serializable {

        private static final long serialVersionUID = 1L;

        private String state;

        private String province;

        private String city;

        

        public Address(String state, String province, String city) {

                super();

                this.state = state;

                this.province = province;

                this.city = city;

        }

        //省略。。。。

        @Override

        public String toString() {

                return "Address [state=" + state + ", province=" + province + ", city=" + city + "]";

        }

}

(3)测试类 Test

    1

    2

    3

    4

    5

    6

    7

    8

    9

   10

   11

   12

   13

   14

   15

   16

   17

   18

   19

   20

   21

   22

   23

   24

   25

   26

   27

   28

   29

   30

   31

   32

   33

   34

   35

public class Test {

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

                System.out.println("序列化之前:");

                Address address = new Address("中国", "吉林", "长春");

                Employee employee = new Employee("张三", 30, address);

                System.out.println(employee.toString());

                

                System.out.println("序列化之后:");

                Employee employee2 = null;

                //序列化到本地

                try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("E:/test/employee.txt")));

                                ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:/test/employee.txt")))) {

                        oos.writeObject(employee);

                        employee2 = (Employee) ois.readObject();

                } catch (IOException e) {

                        e.printStackTrace();

                } catch (ClassNotFoundException e) {

                        e.printStackTrace();

                }

                if(employee2 == null)

                        return;

                employee2.setName("李四");

                employee2.setAge(22);

                employee2.getAddress().setState("中国");

                employee2.getAddress().setProvince("四川");

                employee2.getAddress().setCity("成都");

                System.out.println("employee:" + employee);

                System.out.println("employee2:" + employee2);

                

                System.out.println("___________________________________");

                System.out.println("x.clone() != x  --->" + (employee != employee2));

                System.out.println("x.clone().getClass() == x.getClass() -->"+(employee.getClass() == employee2.getClass()));

                System.out.println("x.clone().equals(x) --->" + employee.equals(employee2));

        }

}

(4)运行结果

 

 

五、序列化和深克隆效率比较:

1、本次实例对 深克隆 和 序列化克隆 方式进行比较,分别使用这两种方式创建 100000 个对象

 2、通过比较发现深克隆所花费的时间远远小于序列化,与序列化每次开销很大有关系

3、代码实现:

(1)Employee 还是员工类,实现Serializable、Cloneable接口

    1

    2

    3

    4

    5

    6

    7

    8

    9

   10

   11

   12

   13

   14

   15

   16

   17

   18

   19

   20

   21

   22

public class Employee implements Serializable, Cloneable {

        //员工的name

        private String name;

        //员工的age

        private int age;

        

        public Employee(String name, int age) {

                super();

                this.name = name;

                this.age = age;

        }

        

        //省略,,,

        @Override

        public String toString() {

                return "姓名:" + name + ",年龄:" + age;

        }

        @Override

        protected Employee clone() throws CloneNotSupportedException {

                return (Employee)super.clone();

        }

}

(2)测试类 Test

    1

    2

    3

    4

    5

    6

    7

    8

    9

   10

   11

   12

   13

   14

   15

   16

   17

   18

   19

   20

   21

   22

   23

   24

   25

   26

   27

   28

   29

   30

   31

public class Test {

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

                //深克隆测试

                List<Employee> employees = new ArrayList<>();

                Employee employee = new Employee("王五", 25);

                long startTime = System.currentTimeMillis();

                for (int i = 0; i < 100000; i++) {

                        employees.add(employee.clone());

                }

                System.out.println("深克隆花费的时间:" + (System.currentTimeMillis() - startTime));

                

                //序列化测试

                List<Employee> employees2 = new ArrayList<>();

                startTime = System.currentTimeMillis();

                for (int i = 0; i < 100000; i++) {

                        //保存于内存中

                        try(ByteArrayOutputStream bos = new ByteArrayOutputStream();

                                        ObjectOutputStream oos = new ObjectOutputStream(bos);

                        ) {

                                oos.writeObject(employee);

                                ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));

                                employees2.add((Employee)ois.readObject());

                        } catch (IOException e) {

                                e.printStackTrace();

                        } catch (ClassNotFoundException e) {

                                e.printStackTrace();

                        }

                }

                System.out.println("序列化花费的时间:"+ (System.currentTimeMillis() - startTime));

        }

}

(3)运行结果

观看《Java经典编程300例》所写

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值