不使用构造方法创建Java对象 Objenesis

分享到:

如果一个类没有参数为空的构造方法时候,那么你直接调用newInstance方法试图得到一个实例对象的时候是会抛出异常的。能不能有 办法绕过构造方法来实例化一个对象呢?

Objenesis 为其提供了在四个不同的jvm上的解决方案。

  •  Sun Hotspot VM, versions 1.3, 1.4, 1.5 and 1.6
  •  GCJ version 3.4.4 (tested on Windows/Cygwin)
  •  BEA JRockit versions 7.0 (1.3.1), 1.4.2 and 1.5
  •  Aonix PERC (no serialization support), tested on version 5.0.0667

从运行平台上得到几个关键的参数,如下:

  1. /** JVM version */  
  2. protected static final String VM_VERSION = System.getProperty("java.runtime.version");   
  3.   
  4. /** JVM version */  
  5. protected static final String VM_INFO = System.getProperty("java.vm.info");   
  6.   
  7. /** Vendor version */  
  8. protected static final String VENDOR_VERSION = System.getProperty("java.vm.version");   
  9.   
  10. /** Vendor name */  
  11. protected static final String VENDOR = System.getProperty("java.vm.vendor");   
  12.   
  13. /** JVM name */  
  14. protected static final String JVM_NAME = System.getProperty("java.vm.name");  

然后根据得到的参数进行判断:

根据得到平台提供的jvm版本和供应商来选择不同的实例化策略。
说实话,这几个平台里面我还 是对sun公司提供的相对熟悉一些,所以除了sun公司提供的jvm对于的实例策略我在这里就不介绍了,
大家有兴趣的话可以去项目主页下载下来细 细研究。

现在我们仅仅关注sun公司的,并且版本大于1.3的。
版本为1.3的jvm具体实例化策略这里不做讨论了,有兴趣的可 以去看objenesis的实现。

代码如下:

  1. import sun.reflect.ReflectionFactory;   
  2. public class SunReflectionFactoryInstantiator implements ObjectInstantiator {   
  3.   
  4. private final Constructor mungedConstructor;   
  5.   
  6. public SunReflectionFactoryInstantiator(Class type) {   
  7.   
  8. ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();   
  9. Constructor javaLangObjectConstructor;   
  10.   
  11. try {   
  12. javaLangObjectConstructor = Object.class.getConstructor((Class[]) null);   
  13. }   
  14. catch(NoSuchMethodException e) {   
  15. throw new Error("Cannot find constructor for java.lang.Object!");   
  16. }   
  17. mungedConstructor = reflectionFactory.newConstructorForSerialization(type,   
  18. javaLangObjectConstructor);   
  19. mungedConstructor.setAccessible(true);   
  20. }   
  21.   
  22. public Object newInstance() {   
  23. try {   
  24. return mungedConstructor.newInstance((Object[]) null);   
  25. }   
  26. catch(Exception e) {   
  27. throw new ObjenesisException(e);   
  28. }   
  29. }   
  30. }   


通过sun.reflect.ReflectionFactory这 个类来实例化一个class那么就绕过了其类的构造方法,我们可以暂且称之为绕道方式实例一个对象。
希望上面的代码能给大家起到一定的帮助,另外easymock的 最新版本已经使用了Objenesis来实例化一个Class获取对象。

项目主页:http://www.open-open.com/lib/view/home/1326941374233

昵    称:
验证码:

相关文档: