JEP 181不兼容,嵌套类/ 2
JEP 181是基于嵌套的訪問控制https://openjdk.java.net/jeps/181 。 它是在Java 11中引入的,它故意引入了與先前版本的不兼容性。 這是一個很好的例子,與Java的先前版本兼容并不是刻板的規則,而是保持語言的一致性和穩定發展。 在本文中,我將通過幾年前遇到的一個例子來研究這種變化,以及在這種特殊情況下Java 11如何使生活更輕松,更一致。
Java向后兼容性僅限于功能而非行為
原始情況
幾年前,當我編寫可以用Java方法擴展的ScriptBasic for Java解釋器時,就好像它們是用BASIC編寫的一樣可用時,我創建了一些單元測試。 單元測試類包含一些內部類,其中具有一些可用于BASIC代碼的方法。 內部類是靜態和私有的,因為它與除測試以外的任何其他類均無關,但是,該類和方法仍可被測試代碼訪問,因為它們位于同一類中。 令我沮喪的是,這些方法無法通過BASIC程序訪問。 當我嘗試通過本身正在使用反射訪問的BASIC解釋器調用方法時,出現了IllegalAccessException 。
為了糾正這種情況,經過幾個小時的調試和學習,我創建了以下簡單代碼:
package javax0;import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;public class ReflThrow {private class Nested {private void m(){System.out.println("m called");}}public static void main(String[] args)throws NoSuchMethodException,InvocationTargetException,IllegalAccessException {ReflThrow me = new ReflThrow();Nested n = me.new Nested();n.m();Method m = Nested.class.getDeclaredMethod("m");m.invoke(n);} }如果使用Java N(其中N <11)運行此代碼,則將得到類似以下內容:
m called Exception in thread "main" java.lang.IllegalAccessException: class ReflThrow cannot access a member of class ReflThrow$Nested with modifiers "private"at java.base/jdk.internal.reflect.Reflection.throwIllegalAccessException(Reflection.java:423)at java.base/jdk.internal.reflect.Reflection.throwIllegalAccessException(Reflection.java:414) ...但是,它可以在Java 11上正常運行(并且大概在更高版本的Java中也可以正常運行)。
說明
直到Java 11版本,JVM都不處理內部和嵌套類。 JVM中的所有類都是頂級類。 Java編譯器從內部和嵌套類創建一個特別命名的頂級類。 例如,其中一個Java編譯器可以創建類文件ReflThrow.class和ReflThrow$Nested.class 。 因為它們是JVM的頂級類,所以當ReflThrow類是兩個不同的頂級類時,它們中的代碼無法調用Nested的私有方法m() 。
但是,在Java級別,從嵌套結構創建這些類是可能的。 為了實現這一點,編譯器在Nested類中創建了一個額外的綜合方法, ReflThrow中的代碼可以調用該方法,而Nested已經存在的該方法將調用m() 。
合成方法具有修飾符SYNTHETIC因此編譯器稍后知道其他代碼不應“看到”這些方法。 這樣,調用方法m()效果很好。
另一方面,當我們嘗試使用名稱和反射訪問來調用方法m() ,路由將直接通過類邊界,而無需調用任何合成方法,并且由于該方法對于它所在的類是私有的,因此調用引發異常。
Java 11對此進行了更改。 結合到已經發布的Java 11中的JEP 181引入了概念嵌套。 “嵌套允許類在邏輯上屬于同一代碼實體,但被編譯成不同的類文件,而無需編譯器插入可擴展訪問性的橋方法,即可訪問彼此的私有成員。” 它僅表示存在作為嵌套的類,并且存在屬于嵌套??的類。 從Java生成代碼時,頂級類是嵌套類,而內部的類是嵌套的。 JVM級別的此結構為不同的語言結構留有很大空間,并且不會在執行環境中出現Java結構的麻煩。 JVM旨在成為多語言的,并且隨著將來GraalVM的引入,它甚至將成為“更多”的多語言。 使用這種結構的JVM只是看到兩個類在同一個嵌套中,因此它們可以互相訪問private方法,字段和其他成員。 這也意味著沒有橋接方法具有不同的訪問限制,并且反射與普通的Java調用完全通過相同的訪問邊界。
摘要/外賣
Java不會一夜之間發生變化,并且大部分是向后兼容的。 但是,向后兼容性僅限于功能而非行為。 JEP181沒有,并且它從未真正打算重現對嵌套類的反射訪問的并非絕對完美的IllegalAccessException拋出行為。 此行為是實現行為/錯誤,而不是語言功能,并且已在Java 11中修復。
翻譯自: https://www.javacodegeeks.com/2018/10/jep-181-incompatibility-nesting-classes.html
總結
以上是生活随笔為你收集整理的JEP 181不兼容,嵌套类/ 2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一加手表要来了!目前正在积极开发中 功能
- 下一篇: 使用LocalDate,LocalTim