隐藏类是什么?
隐藏类是其他类不能直接使用的类。引入隐藏类的主要目的是使用框架,使框架在运行过程中生成类,并通过反射间接使用。它可能有点抽象。没关系。让我们通过一个例子直观地理解它!
隐藏类案例
:先创造一个普通的Java类
public class JEP371HiddenClasses { public static String hello() { return "https://www.didispace.com"; } }
:编译或编译后class文件。然后使用Base64对文件内容Encode,您可以使用各种工具或以下代码:
String filePath = "JEP371HiddenClasses.class"; byte[] b = Files.readAllBytes(Paths.get(filePath)); log.info(Base64.getEncoder().encodeToString(b));
执行以下内容:
yv66vgAAAD0AFAoAAgADBwAEDAAFAAYBABBqYXZhL2xhbmcvT2JqZWN0AQAGPGluaXQ AQADKClWCAAIAQAZaHR0cHM6Ly93d3cuZGlkaXNwYWNlLmNvbQcACgEALmNvbS9kaWRpc3BhY2UvZGVidWcvamF2YTE1L0pFUDM3MUhpZGRlbkNsYXNzZXMBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAMExjb20vZGlkaXNwYWNlL2RlYnVnL2phdmExNS9KRVAzNzFIaWRkZW5DbGFzc2VzOwEABWhlbGxvAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAApTb3VyY2VGaWxlAQAYSkVQMzcxSGlkZGVuQ2xhc3Nlcy5qYXZhACEACQACAAAAAAACAAEABQAGAAEACwAAAC8AAQABAAAABSq3AAGxAAAAAgAMAAAABgABAAAAAwANAAAADAABAAAABQAOAA8AAAAJABAAEQABAAsAAAAbAAEAAAAAAAMSB7AAAAABAAwAAAAGAAEAAAAGAAEAEgAAAAIAEw==
这个内容是第一步写的。
:通过反射加载生成的类,并调用隐藏类hello代码如下:函数:
/** * 程序猿DD * <a href="https://www.didispace.com/java-features/">Java新特性解读</a> */ @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()); // 输出类有哪些函数? for(Method method : proxy.getDeclaredMethods()) { log.info(method.getName()); } // 2. 调用hello函数 MethodHandle mh = MethodHandles.lookup().findStatic(proxy, "hello", MethodType.methodType(String.class)); String result = (String) mh.invokeExact(); log.info(result); }
具体的执行逻辑并不冗长,读者可以根据注释来理解。本测试内容的最终执行可获得以下输出:
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
- 第一行:输出这个隐藏类的类名
- 第二行:输出隐藏类下的方法名称
- 第三行:调用隐藏类下hello方法获得的返回内容
挺简单的吗?
如果你像我一样参与一些基本框架的开发,你一定认为这个功能很好!
本文首发:Java 15 新特点:隐藏类 本期视频:Java 15 新特点:隐藏类
今天的分享到此为止!如果你在学习过程中遇到困难?您可以加入我们的高质量技术交流小组,参与交流和讨论,更好地学习和进步!
欢迎关注我的微信官方账号:程序猿DD。前沿技术早就知道了,弯道超车是有希望的!积累超车资本,关注DD开始!