`

关于对象的创建(new)与克隆(clone),包括其他方式的提供的克隆 的简单分析

    博客分类:
  • java
 
阅读更多

  在Java中得到对象一般有两种情况。第一使用new创建,这是经常用的方式;第二使用clone方式,这种方式比较生僻。看过一些文章和书籍,比如《Java程序性能优化:让你的Java程序更快、更稳定》中提到推荐使用clone的方式(第137页)。

下面就这两种方式进行测试:

先来一个User类

Java代码  收藏代码
  1. /** 
  2.  * 实体类 
  3.  * @author chdyan 
  4.  * @date 2014-10-20 
  5.  * @since jdk1.6 
  6.  */  
  7. public class User implements Serializable, Cloneable {  
  8.       
  9.     private static final long serialVersionUID = -1757309588653207550L;  
  10.     //用户名  
  11.     private String username;  
  12.     //密码  
  13.     private transient String password;  
  14.     //出生日期  
  15.     private Date birthDay;  
  16.     //地址  
  17.     private String address;  
  18.       
  19.     public String getUsername() {  
  20.         return username;  
  21.     }  
  22.     public void setUsername(String username) {  
  23.         this.username = username;  
  24.     }  
  25.     public String getPassword() {  
  26.         return password;  
  27.     }  
  28.     public void setPassword(String password) {  
  29.         this.password = password;  
  30.     }  
  31.     public Date getBirthDay() {  
  32.         return birthDay;  
  33.     }  
  34.     public void setBirthDay(Date birthDay) {  
  35.         this.birthDay = birthDay;  
  36.     }  
  37.     public String getAddress() {  
  38.         return address;  
  39.     }  
  40.     public void setAddress(String address) {  
  41.         this.address = address;  
  42.     }  
  43.     @Override  
  44.     public Object clone() {  
  45.         User user = null;  
  46.         try {  
  47.             user = (User) super.clone();  
  48.             user.username = this.username;  
  49.             if(this.birthDay != null)  
  50.                 user.birthDay = (Date) this.birthDay.clone();  
  51.             user.address = this.address;  
  52.         } catch (CloneNotSupportedException e) {  
  53.             e.printStackTrace();  
  54.         }  
  55.         return user;  
  56.     }  
  57. }  

 

 下面进行没有属性值的测试:

Java代码  收藏代码
  1. /** 
  2.  * @author chdyan 
  3.  * @Date 2014-10-20 
  4.  */  
  5. public class CloneTest {  
  6.     public static void main(String[] args) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {  
  7.         User user = new User();  
  8.         //-----------使用new的方式创建---------------  
  9.         long begin = System.nanoTime();  
  10.         for(int i=0; i<10000; i++) {  
  11.             new User();  
  12.         }  
  13.         System.out.println("---------------new方式创建:" + (System.nanoTime() - begin));  
  14.           
  15.         //-----------使用clone的方式创建---------------  
  16.         begin = System.nanoTime();  
  17.         for(int i=0; i<10000; i++) {  
  18.             user.clone();  
  19.         }  
  20.         System.out.println("-------------clone方式创建:" + (System.nanoTime() - begin));  
  21.           
  22.         //-----------使用commons-lang3的SerializationUtils的所谓clone方式创建---------------  
  23.         begin = System.nanoTime();  
  24.         for(int i=0; i<10000; i++) {  
  25.             SerializationUtils.clone(user);  
  26.         }  
  27.         System.out.println("SerializationUtils方式创建:" + (System.nanoTime() - begin));  
  28.           
  29.         //-----------使用commons-beanutils的BeanUtils的所谓cloneBean方式创建---------------  
  30.         begin = System.nanoTime();  
  31.         for(int i=0; i<10000; i++) {  
  32.             BeanUtils.cloneBean(user);  
  33.         }  
  34.         System.out.println("---------BeanUtils方式创建:" + (System.nanoTime() - begin));  
  35.     }  
  36. }  

 

结果为:

 

或许会有疑问,user的clone方法里还有赋值呢。当然慢了。那好,我就把User类中的赋值语句去了,改成如下。

Java代码  收藏代码
  1. @Override  
  2.     public Object clone() {  
  3.         User user = null;  
  4.         try {  
  5.             user = (User) super.clone();  
  6.         } catch (CloneNotSupportedException e) {  
  7.             e.printStackTrace();  
  8.         }  
  9.         return user;  
  10.     }  

 

看下结果



 依旧不是一个数量级的。

测试使用jdk1.6.0.45可以看出,new方式比clone方式快多了。SerializationUtils的clone原理其实是使用了序列化的方式,是最慢的。BeanUtils的cloneBean的原理是创建对象然后给对象的成员变量拷贝值的方式。

 空对象,不进行复制,是最快的。

 

-------------------------------------------------华丽的分隔线-----------------------------------------------------------------------

 

下面给参数都赋值来测试下,new和clone方式创建对象哪个快,包括增加BeanUtils的copyProperties方法和Properties的copyProperties方法,共同比较下。测试方法如下:

 

Java代码  收藏代码
  1. /** 
  2.  * @author chdyan 
  3.  * @Date 2014-10-20 
  4.  */  
  5. public class CloneTest {  
  6.     public static void main(String[] args) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {  
  7.         Date now = new Date();  
  8.         //由于String对象是不可变的。  
  9.         String username = "ChdYan";  
  10.         String password = "123456";  
  11.         String address = "中国,广东";  
  12.         User user = new User();  
  13.         user.setUsername(username);  
  14.         user.setPassword(password);  
  15.         user.setBirthDay(now);  
  16.         user.setAddress(address);  
  17.         //----------------初始化数据------------------------  
  18.         int i=0int j=10000;  
  19.           
  20.         //-----------使用new的方式创建---------------  
  21.         User u = null;  
  22.         long begin = System.nanoTime();  
  23.           
  24.         for(i=0; i<j; i++) {  
  25.             u = new User();  
  26.             //由于String对象是不可变的。  
  27.             u.setUsername(username);  
  28.             u.setPassword(password);  
  29.             u.setBirthDay(new Date());  
  30.             u.setAddress(address);  
  31.         }  
  32.         System.out.println("--------------------------new方式创建:" + (System.nanoTime() - begin));  
  33.           
  34.         //-----------使用clone的方式创建---------------  
  35.         begin = System.nanoTime();  
  36.         for(i=0; i<j; i++) {  
  37.             user.clone();  
  38.         }  
  39.         System.out.println("------------------------clone方式创建:" + (System.nanoTime() - begin));  
  40.           
  41.         //-----------使用commons-lang3的SerializationUtils的所谓clone方式创建---------------  
  42.         begin = System.nanoTime();  
  43.         for(i=0; i<j; i++) {  
  44.             SerializationUtils.clone(user);  
  45.         }  
  46.         System.out.println("----SerializationUtils的clone方式创建:" + (System.nanoTime() - begin));  
  47.           
  48.         //-----------使用commons-beanutils的BeanUtils的所谓cloneBean方式创建---------------  
  49.         begin = System.nanoTime();  
  50.         for(i=0; i<j; i++) {  
  51.             BeanUtils.cloneBean(user);  
  52.         }  
  53.         System.out.println("---------BeanUtils的cloneBean方式创建:" + (System.nanoTime() - begin));  
  54.           
  55.         //-----------使用commons-beanutils的BeanUtils的所谓copyProperties方式创建---------------  
  56.         begin = System.nanoTime();  
  57.         for(i=0; i<j; i++) {  
  58.             u = new User();  
  59.             BeanUtils.copyProperties(u, user);  
  60.         }  
  61.         System.out.println("----BeanUtils的copyProperties方式创建:" + (System.nanoTime() - begin));  
  62.           
  63.         //-----------使用commons-beanutils的BeanUtils的所谓copyProperties方式创建---------------  
  64.         begin = System.nanoTime();  
  65.         for(i=0; i<j; i++) {  
  66.             u = new User();  
  67.             PropertyUtils.copyProperties(u, user);  
  68.         }  
  69.         System.out.println("PropertyUtils的copyProperties方式创建:" + (System.nanoTime() - begin));  
  70.     }  
  71. }  

  

 

 可以看到每一个对象都已经赋值了,结果如下:



 
 new方式还是要比clone方式快多。如果觉得string对象太多了,可以去User类中增加一两个Date成员变量。通过本人亲自测试,测试结果也一样。

 

所以,创建对象使用new创建,只是很常见的,jvm也对其进行了深度优化。而clone方式,是比较生僻的使用方法。 数据结果中可以看到BeanUtils的cloneBean和copyProperties时间比较接近,两者是使用共同的拷贝成员变量方法。PropertyUtils的copyProperties的速度比BeanUtils快多了。虽然说手动设置比使用类库拷贝成员方法快些,但是为了通用性,设计的简洁,推荐使用PropertyUtils的copyProperties的拷贝方法

分享到:
评论
1 楼 chongdiyang 2015-07-13  
       

相关推荐

    clone 深度克隆对象

    这意味着如果一个对象中包含了其他对象的引用,深度克隆会创建这些引用对象的独立副本,而不是简单地复制引用。因此,即使原始对象被修改,深克隆后的副本也不会受到影响,从而提供了数据安全性。 在Java中,实现...

    clone()方法示例(对象克隆)_对象克隆_nervouse78_源码

    但是,需要注意的是,`clone()`方法返回的是一个浅拷贝,即如果对象的属性包含其他对象引用,那么这两个对象引用指向的是同一块内存空间,而不是完全独立的副本。 在`nervouse78`的这个示例中,作者"初生不惑"可能...

    对象克隆(clone)详解.docx

    2. 深克隆:深克隆旨在创建一个与原始对象完全独立的副本,包括其内部引用的对象。如果一个对象包含对可变(非静态)对象的引用,深克隆会递归地克隆这些内部对象,确保新对象内部的引用指向新的、独立的对象副本。...

    Java对象的深克隆与浅克隆详解.zip(wcb2003)

    Java提供了两种主要的克隆方式:浅克隆(Shallow Clone)和深克隆(Deep Clone)。下面我们将深入探讨这两种克隆方法。 ### 浅克隆 浅克隆是指创建一个新的对象,其成员变量的值与原对象相同,但引用类型成员变量...

    C#中Clone一个对象的值到另一个对象案例 c#经典案例.pdf

    在上面的代码中,我们创建了一个 A 对象 t1,然后使用 Clone 方法将其复制到另一个对象 t2 中。我们可以看到,t2 中的字段值都是 t1 的副本。然后,我们修改了 t2 中的字段值,但 t1 中的字段值保持不变。 结论 在...

    Java对象的复制克隆

    总之,Java中的对象复制与克隆是程序设计中重要的概念,它提供了创建对象副本的能力,而不会影响原始对象的状态。浅拷贝适用于简单的对象,而深拷贝则用于处理复杂的数据结构,确保对象之间的独立性。在实际应用中,...

    在Unity3D中实现克隆脚本2

    首先,Unity3D提供了两种主要的克隆方式:`Instantiate`函数和克隆实例化。`Instantiate`是Unity内置的函数,可以用于创建对象的副本。在提供的部分内容中,我们可以看到一个使用`Instantiate`的例子,克隆了一个名...

    java 深克隆 浅克隆

    在Java编程语言中,克隆是一种创建对象副本的方法,它允许我们复制一个对象并得到一个与原对象相同但独立的新对象。克隆分为两种主要类型:深克隆和浅克隆。理解这两种克隆的区别是Java面向对象编程中的重要概念。 ...

    java四种创建对象的方式

    Java中创建对象主要有四种显式的方式,分别是使用new关键字、反射机制、克隆克隆方法以及反序列化手段。每种方法都有其特定的使用场景和特点,以下是这些方法的详细说明: 1. 使用new关键字创建对象 这是最常见也是...

    JAVA浅克隆与深克隆

    在Java编程语言中,克隆是创建一个对象副本的过程,这个副本与原对象有相同的属性值,但作为不同的对象存在。克隆分为两种主要类型:浅克隆(Shallow Clone)和深克隆(Deep Clone)。这篇博客文章将探讨这两种克隆...

    java 对象克隆

    在Java编程语言中,对象克隆是一种创建一个与原对象具有相同数据的新对象的过程。对象克隆主要用于复制或备份对象,以便在不干扰原始对象的情况下对其进行修改或操作。本篇文章将详细探讨Java中的对象克隆及其实现...

    alibaba.com new PHP clone 英文版阿里巴巴克隆 PHP完整版源码

    【标题】"alibaba.com new PHP clone 英文版阿里巴巴克隆 PHP完整版源码" 涉及的核心知识点主要集中在PHP编程语言、网站克隆技术以及阿里巴巴网站的架构和功能模仿。这个项目是一个用于教学目的的开源版本,旨在帮助...

    java对象复制克隆

    标题中的“java对象复制克隆”主要涉及的是深拷贝,这是一种创建一个新对象的方式,新对象不仅复制了原对象的所有属性,还复制了嵌套的对象引用,使得修改复制后的对象不会影响到原始对象。 **浅拷贝**:在浅拷贝中...

    PHP面向对象程序设计之对象克隆clone和魔术方法__clone()用法分析

    通过这两个工具,我们可以创建对象的副本,同时根据需要调整克隆对象的状态。在特定情况下,如实现单例模式,我们还可以控制是否允许对象被克隆。理解和熟练运用这些机制,有助于编写更灵活、更高效的代码。

    java的深度克隆的例子

    但需要注意的是,`clone()`方法默认执行的是浅克隆,因此如果对象中包含对其他对象的引用,这些引用不会被复制。为了实现深度克隆,我们需要手动处理这些引用,通常通过序列化和反序列化的方式。 以下是实现深度...

    java深度克隆

    在Java中,深度克隆是一种用于创建对象副本的方法,它可以确保复制出的新对象与原对象之间没有任何引用关系,也就是说,新对象中的所有成员变量(包括引用类型)都是原对象对应成员变量的副本。这种特性使得深度克隆...

    Java深浅clone

    浅克隆是指创建一个新对象,它的字段与原始对象的字段具有相同的引用。这意味着,如果对象的字段包含可变对象(如数组或集合),那么修改副本的这些字段也会影响原始对象,因为它们共享同一个内存引用。 深克隆则是...

    java clone的小例子

    总之,`clone()`方法在Java中提供了对对象复制的基本支持,尤其适用于需要创建对象副本的情况。然而,由于其浅拷贝的特性,开发者需要根据具体需求来决定是否使用它,或者选择其他复制策略,比如序列化和反序列化,...

Global site tag (gtag.js) - Google Analytics