`

关于对象的创建(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  
       

相关推荐

Global site tag (gtag.js) - Google Analytics