Java 12 中引入 JVM 常量 API,用來更容易地對關鍵類文件 (key class-file) 和運行時構件(artefact)的名義描述
(nominal description) 進行建模,特別是對那些從常量池加載的常量,這是一項非常技術性的變化,能夠以更簡
單、標准的方式處理可加載常量。
具體來說就是java.base模塊新增了java.lang.constant包(而非 java.lang.invoke.constant )。包中定義了一系列基於值的符號引用(JVMS 5.1)類型,它們能夠描述每種可加載常量。
官方api鏈接地址:
http://cr.openjdk.java.net/~iris/se/12/latestSpec/api/java.base/java/lang/constant/pack
age-summary.html
Java SE > Java SE Specifications > Java Virtual Machine Specification下的第5章:
Chapter 5. Loading, Linking, and Initializing
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html
引入了ConstantDesc接口( ClassDesc、MethodTypeDesc、MethodHandleDesc這幾個接口直接繼承了ConstantDesc接口)以及Constable接口;ConstantDesc接口定義了resolveConstantDesc方法,Constable接口定義了describeConstable方法;String、Integer、Long、Float、Double均實現了這兩個接口,而EnumDesc實現了ConstantDesc接口。

符號引用以純 nominal 形式描述可加載常量,與類加載或可訪問性上下文區分開。有些類可以作為自己的符號引用(例如 String)。而對於可鏈接常量,另外定義了一系列符號引用類型,具體包括: ClassDesc (Class 的可加載常量標稱描述符) ,MethodTypeDesc(方法類型常量標稱描述符) ,MethodHandleDesc (方法句柄常量標稱描述符) 和DynamicConstantDesc (動態常量標稱描述符) ,它們包含描述這些常量的 nominal 信息。此 API 對於操作類和方法的工具很有幫助。
String 實現了 Constable 接口:
public final class String implements java.io.Serializable, Comparable<String>,
CharSequence,Constable, ConstantDesc {
java.lang.constant.Constable接口定義了抽象方法:
public interface Constable {
Optional<? extends ConstantDesc> describeConstable();
}
Java 12 String 的實現源碼:
@Override
public Optional<String> describeConstable() {
return Optional.of(this);
}
很簡單,其實就是調用 Optional.of 方法返回一個 Optional 類型。
String#describeConstable和resolveConstantDesc
新引入的接口java.lang.constant.Constable - 它用於標記constable類型,這意味着這類型的值是常量,可以在JVMS 4.4常量池中定義。
Java SE > Java SE Specifications > Java Virtual Machine Specification下的第4章:
Chapter 4. The class File Format
String的源碼:
/**
* Returns an {@link Optional} containing the nominal descriptor for this
* instance, which is the instance itself.
*
* @return an {@link Optional} describing the {@linkplain String} instance
* @since 12
*/
@Override
public Optional<String> describeConstable() {
return Optional.of(this);
}
/**
* Resolves this instance as a {@link ConstantDesc}, the result of which is
* the instance itself.
*
* @param lookup ignored
* @return the {@linkplain String} instance
* @since 12
*/
@Override
public String resolveConstantDesc(MethodHandles.Lookup lookup) {
return this;
}
private static void testDescribeConstable() {
System.out.println("======test java 12 describeConstable======");
String name = "Java高級工程師";
Optional<String> optional = name.describeConstable();
System.out.println(optional.get());
}
