你知道 Java 中的隱藏類嗎?
前幾天給大家介紹了Java 17中新推出的密封類,今天繼續(xù)給大家介紹一個(gè)Java 15開始推出的一個(gè)新內(nèi)容:隱藏類。
如果你喜歡做封裝、做框架的話,這個(gè)內(nèi)容可能對(duì)你很有用哦!
什么是隱藏類
隱藏類,是一種不能被其他類直接使用的類。引入隱藏類的主要目的是給框架來使用,使得框架可以在運(yùn)行時(shí)生成類,并通過反射間接使用它們。
可能有點(diǎn)抽象,不要緊,下面我們通過一個(gè)例子來直觀的認(rèn)識(shí)它!
如果你關(guān)注Java前沿知識(shí),記得關(guān)注公眾號(hào):程序猿DD,持續(xù)分享前沿技術(shù)內(nèi)容,積累普通技術(shù)人的彎道超車資本!
隱藏類案例
第一步:先創(chuàng)建一個(gè)普通的Java類
public?class?JEP371HiddenClasses?{
????public?static?String?hello()?{
????????return?"https://www.didispace.com";
????}
}
第二步:編譯一下,或得編譯后的class文件。然后使用Base64對(duì)文件內(nèi)容Encode,你可以用各種工具,也可以用下面代碼來獲取:
String?filePath?=?"JEP371HiddenClasses.class";
byte[]?b?=?Files.readAllBytes(Paths.get(filePath));
log.info(Base64.getEncoder().encodeToString(b));
執(zhí)行一下,獲取到內(nèi)容如下:
yv66vgAAAD0AFAoAAgADBwAEDAAFAAYBABBqYXZhL2xhbmcvT2JqZWN0AQAGPGluaXQ+AQADKClWCAAIAQAZaHR0cHM6Ly93d3cuZGlkaXNwYWNlLmNvbQcACgEALmNvbS9kaWRpc3BhY2UvZGVidWcvamF2YTE1L0pFUDM3MUhpZGRlbkNsYXNzZXMBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAMExjb20vZGlkaXNwYWNlL2RlYnVnL2phdmExNS9KRVAzNzFIaWRkZW5DbGFzc2VzOwEABWhlbGxvAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAApTb3VyY2VGaWxlAQAYSkVQMzcxSGlkZGVuQ2xhc3Nlcy5qYXZhACEACQACAAAAAAACAAEABQAGAAEACwAAAC8AAQABAAAABSq3AAGxAAAAAgAMAAAABgABAAAAAwANAAAADAABAAAABQAOAA8AAAAJABAAEQABAAsAAAAbAAEAAAAAAAMSB7AAAAABAAwAAAAGAAEAAAAGAAEAEgAAAAIAEw==
這個(gè)內(nèi)容就是第一步寫的類。
第三步:通過反射加載上面生成的類,并調(diào)用隱藏類中的hello函數(shù),代碼如下:
/**
?*?程序猿DD
?*?Java新特性解讀
?*/
@Test
void?testHiddenClasses()?throws?Throwable?{
??//?1.?加載encode之后的隱藏類
??String?CLASS_INFO?=?"yv66vgAAAD0AFAoAAgADBwAEDAAFAAYBABBqYXZhL2xhbmcvT2JqZWN0AQAGPGluaXQ+AQADKClWCAAIAQAZaHR0cHM6Ly93d3cuZGlkaXNwYWNlLmNvbQcACgEALmNvbS9kaWRpc3BhY2UvZGVidWcvamF2YTE1L0pFUDM3MUhpZGRlbkNsYXNzZXMBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAMExjb20vZGlkaXNwYWNlL2RlYnVnL2phdmExNS9KRVAzNzFIaWRkZW5DbGFzc2VzOwEABWhlbGxvAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAApTb3VyY2VGaWxlAQAYSkVQMzcxSGlkZGVuQ2xhc3Nlcy5qYXZhACEACQACAAAAAAACAAEABQAGAAEACwAAAC8AAQABAAAABSq3AAGxAAAAAgAMAAAABgABAAAAAwANAAAADAABAAAABQAOAA8AAAAJABAAEQABAAsAAAAbAAEAAAAAAAMSB7AAAAABAAwAAAAGAAEAAAAGAAEAEgAAAAIAEw==";
??byte[]?classInBytes?=?getDecoder().decode(CLASS_INFO);
??Class>?proxy?=?MethodHandles.lookup()
????.defineHiddenClass(classInBytes,?true,?MethodHandles.Lookup.ClassOption.NESTMATE)
????.lookupClass();
??//?輸出類名
??log.info(proxy.getName());
??//?輸出類有哪些函數(shù)
??for(Method?method?:?proxy.getDeclaredMethods())?{
????log.info(method.getName());
??}
??//?2.?調(diào)用hello函數(shù)
??MethodHandle?mh?=?MethodHandles.lookup().findStatic(proxy,?"hello",?MethodType.methodType(String.class));
??String?result?=?(String)?mh.invokeExact();
??log.info(result);
}
具體執(zhí)行邏輯就不啰嗦了,讀者可以根據(jù)注釋來理解。最后執(zhí)行這個(gè)測(cè)試內(nèi)容,可以獲得如下輸出:
17:20:50.360?[main]?INFO?com.didispace.debug.java15.JEP371Test?-?com.didispace.debug.java15.JEP371HiddenClasses/0x0000000800cb0c00
17:20:50.361?[main]?INFO?com.didispace.debug.java15.JEP371Test?-?hello
17:20:50.361?[main]?INFO?com.didispace.debug.java15.JEP371Test?-?https://www.didispace.com
第一行:輸出了這個(gè)隱藏類的類名 第二行:輸出了這個(gè)隱藏類下的方法名稱 第三行:調(diào)用隱藏類下的hello方法獲得的返回內(nèi)容
是不是還挺簡(jiǎn)單?如果你跟我一樣平時(shí)會(huì)參與一些基礎(chǔ)框架和平臺(tái)的開發(fā)工作的話,一定覺得這個(gè)功能還挺不錯(cuò)的吧,畢竟又多了一種動(dòng)態(tài)功能的實(shí)現(xiàn)手段!
好了,今天的分享就到這里!關(guān)于Java新特性這個(gè)專題,我正在連載Java新特性專欄:https://www.didispace.com/java-features/,文檔形式看Java新特性,閱讀學(xué)習(xí)體驗(yàn)更佳!
推薦閱讀
你好,我是程序猿DD,10年開發(fā)老司機(jī)、阿里云MVP、騰訊云TVP、出過書創(chuàng)過業(yè)、國(guó)企4年互聯(lián)網(wǎng)6年。從普通開發(fā)到架構(gòu)師、再到合伙人。一路過來,給我最深的感受就是一定要不斷學(xué)習(xí)并關(guān)注前沿。只要你能堅(jiān)持下來,多思考、少抱怨、勤動(dòng)手,就很容易實(shí)現(xiàn)彎道超車!所以,不要問我現(xiàn)在干什么是否來得及。如果你看好一個(gè)事情,一定是堅(jiān)持了才能看到希望,而不是看到希望才去堅(jiān)持。相信我,只要堅(jiān)持下來,你一定比現(xiàn)在更好!如果你還沒什么方向,可以先關(guān)注我,這里會(huì)經(jīng)常分享一些前沿資訊,幫你積累彎道超車的資本。
