Reputation: 2633
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 on JShell
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
Upvotes: 2
Views: 478
Reputation: 103813
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.
Upvotes: 4
Reputation: 274423
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.
Upvotes: 4