1. 程式人生 > >不通過建構函式來建立類的例項 - Unsafe的使用

不通過建構函式來建立類的例項 - Unsafe的使用

我們知道,當使用反射構造類的例項時,我們常會用到xxx.class.newInstance()這個方法。但是這個方法有一個限制,就是要求類必須有預設的建構函式。但我們在做框架的時候,很難保證要動態構造的類例項,都是有預設建構函式的,那怎麼辦呢?

 

其實用過C++或者Delphi的都知道,其實構造一個物件,分配記憶體和呼叫建構函式實際是兩個不同的步驟。我們要建立一個物件,實際只需要分配它的記憶體就可以了

 

那Java中是否有這樣的解決方案呢?答案是:有的其實在使用xstream做反序列化時,我一直就覺得很神奇,明明我要反序列化的物件是沒有預設建構函式的,它居然也能把它反序列化出來,這到底是怎麼弄的呢?於是我跟蹤了原始碼,就發現了一個Java中很隱蔽的東西,那就是Unsafe類。這個類預設是被隱藏了起來的,甚至連包名都要手動敲(sun.misc.Unsafe),它的用法是這樣的:

Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");

unsafeField.setAccessible(true);

Unsafe u = (Unsafe) unsafeField.get(null);

MyObject obj = (MyObject) u.allocateInstance(MyObject.class);

我們可以看到,這段程式碼,實際就是繞過了建構函式,只分配了物件例項。這樣我們就可以拿著物件例項進行各種操作了。這為反序列化,還有框架的構建,帶來了極大的方便,不會有“需要預設建構函式”這樣的認為約束了