不使用構造方法創建Java對象 Objenesis

fmms 12年前發布 | 51K 次閱讀 Java Java開發

如果一個類沒有參數為空的構造方法時候,那么你直接調用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");  
</div>

然后根據得到的參數進行判斷:

根據得到平臺提供的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. }   
</div>


通過sun.reflect.ReflectionFactory這 個類來實例化一個class那么就繞過了其類的構造方法,我們可以暫且稱之為繞道方式實例一個對象。
希望上面的代碼能給大家起到一定的幫助,另外easymock的 最新版本已經使用了Objenesis來實例化一個Class獲取對象。

項目主頁:http://www.baiduhome.net/lib/view/home/1326941374233

 本文由用戶 fmms 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!