不通過構造函數來創建類的實例 - 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);

我們可以看到,這段代碼,實際就是繞過了構造函數,只分配了對象實例。這樣我們就可以拿着對象實例進行各種操作了。這爲反序列化,還有框架的構建,帶來了極大的方便,不會有“需要默認構造函數”這樣的認爲約束了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章