java如何不通過構造函數創(chuàng)建對象(Unsafe)
java中不通過構造函數創(chuàng)建對象
(也有說不創(chuàng)建對象直接執(zhí)行成員方法)
這里就不和你們扯什么通過 反序列化、clone等方法了 個人覺得都是在胡扯。
如何不執(zhí)行構造函數創(chuàng)建對象?
先來帶大家認識一個類 sun.misc.Unsafe
該類主要提供一些直接訪問系統(tǒng)內存資源等等(學過C語言的應該知道和C語言中的指針一樣),但是由于此類能夠直接操作內存,這無疑也增加了程序的安全風險。所以技術不是那么好的千萬不要在應用中直接使用喲。
從上圖可以看出 java是不允許直接創(chuàng)建該類對象的,但是我們可以看到第一個紅框哪里明顯有個Unsafe類的對象,該類是單例的。 那么怎么獲取該類的實例呢?
注意:本版較低的jdk可能沒有這個方法
有一個getUnsafe()方法,但是很不幸,該方法是提供給jdk內部使用的。我們直接調用該方法會拋異常的。
具體原理就是該類會判斷當前調用這個方法的類是不是由Bootstrap類加載器加載的。
那么如何獲取這個Unsafe實例呢?
有兩種方法
- 一、讓我們使用了Unsafe對象的類通過Bootstrap加載
- 二、熟悉反射的同學就會心頭一冷笑,這還不簡單嗎?是的,我們可以直接通過反射獲取
這里只講通過反射獲取的方式
獲取Unsafe對象
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); Unsafe unsafe = (Unsafe) theUnsafe.get(null);
java基礎好的同學,這段代碼應再熟悉不過了
不執(zhí)行構造函數創(chuàng)建對象?
Unsafe類中有一個 sun.misc.Unsafe#allocateInstance
方法, 接收一個Class<?> 類型對象,然后返回該類的一個對象
我們準備一個測試類
class Test{ private String name; public Test(){ System.out.println("test construct"); } }
該類構造方法私有,然后構造方法中打印了一句話,也就是,只要你創(chuàng)建一個新的對象就會打印這句話。
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); Unsafe unsafe = (Unsafe) theUnsafe.get(null); Test test = (Test) unsafe.allocateInstance(Test.class);
測試代碼
上面這段代碼是沒有任何輸出的,也就是沒有執(zhí)行構造方法,但是卻返回了一個對象
因此也聽有人說 壓根就沒有創(chuàng)建對象, 這我也不好說有沒有創(chuàng)建對象,因為對于底層具體怎么實現的我也不造,但是我更傾向于是沒有執(zhí)行構造方法創(chuàng)建對象這種說法吧。
總結以及注意事項
通過這篇文章我們知道原來java中也提供了直接操作內存的類,而且該類還能不執(zhí)行構造方法就返回一個對象,不過因此也有注意,Unsafe類是直接操作內存的,所以他所分配的內存jvm的垃圾收集器是無法釋放的。該類操作的內存和C語言中一樣,要手動釋放。
關于該類的更多使用方式可到網上找相關的資料
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
在 Spring Boot 3 中接入生成式 AI的操作方法
本文介紹了如何在SpringBoot3中集成生成式AI,以OpenAI的GPT模型為例,通過代碼示例展示了如何實現,SpringBoot3的優(yōu)勢和OpenAI的生成式AI技術結合,為開發(fā)者提供了高效集成生成式AI的方法,感興趣的朋友跟隨小編一起看看吧2025-01-01springcloud整合gateway實現網關全局過濾器功能
本文主要介紹了springcloud整合gateway實現網關全局過濾器功能,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02Spring AOP如何實現注解式的Mybatis多數據源切換詳解
這篇文章主要給大家介紹了關于Spring AOP如何實現注解式的Mybatis多數據源切換的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-11-11