简体   繁体   中英

Java Records Reflection and Synthetic Methods

Based on the older Java (7) Language Specifications (13.1.7) :

Any constructs introduced by a Java compiler that do not have a corresponding construct in the source code must be marked as synthetic, except for default constructors, the class initialization method, and the values and valueOf methods of the Enum class.

On newer ones ( Java (17) Language Specifications (13.1.7) : ) that wording changes to:

A construct emitted by a Java compiler must be marked as synthetic if it does not correspond to a construct declared explicitly or implicitly in source code, unless the emitted construct is a class initialization method (JVMS §2.9).

I wonder how would this apply to the accesor methods created for the components of java Records (JEP 395)

For example

record ARecord(int a){}

would have a method int a() yet there is no code representing such method, according to the wording of the older JLS such method is added by the compiler so I would expect it to be synthetic but its not, as it can be corroborated by running the following 2 lines onJShell

jshell
|  Welcome to JShell -- Version 17.0.1
|  For an introduction type: /help intro

jshell> record ARecord(int a){}
|  created record ARecord

jshell> ARecord.class.getDeclaredMethod("a").isSynthetic();
$2 ==> false

jshell>

The reason I ask is because I would like to use reflection (or any other programmatic mean at runtime) to determine which elements on the class have a matching code structure, basically those have code representing them, meaning:

For the following code

record ARecord(int a){

  pubic void someMethod() {}

}

that entity would have 2 methods ( a and someMethod ), a has no code representing it and someMethod does, I need a way to differentiate those based on that criteria

I wonder if it is because its considered as implicitly declared being its code implicitly defined as part of the component

This is exactly it. Note how the old spec only says that "synthetic" should be marked on constructs that

do not have a corresponding construct in the source code

with the exception of the implicitly declared Enum.values and Enum.valueOf . Back then, those were the only two implicitly declared (in the sense that the new spec uses the phrase) things, apparently. :D

On the other hand, the new spec says

does not correspond to a construct declared explicitly or implicitly in source code

Note that this wording automatically handles the Enum exceptions, but also handles the plethora of implicitly declared things that got added since. This includes record components.

From the Java 17 spec §8.10.3. Record Members ,

Furthermore, for each record component, a record class has a method with the same name as the record component and an empty formal parameter list. This method, which is declared explicitly or implicitly, is known as an accessor method.

...

If a record class has a record component for which an accessor method is not declared explicitly, then an accessor method for that record component is declared implicitly [...]

The method a is implicitly declared in your component, therefore it is not synthetic.

Generally speaking (there might be exceptions to this that I don't know of), synthetic constructs are constructs that are not specified by the language spec, but are required for a particular implementation of a compiler to work. The spec is basically saying that such constructs must be marked as "synthetic" in the binary. See some examples here .

Any members of a type that have the synthetic flag on are ignored entirely by javac . Javac acts exactly as if those things don't exist at all.

As a consequence, obviously, the 'getters' you get for a record aren't synthetic. If they were, it would be impossible to call them from .java code - the only way to call them is to write a hacky javac clone that does compile access to synthetics, or to use bytecode manipulation to remove the synthetic flag, or to emit bytecode directly, or to use reflection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM