[Records] Component annotations not propagated when explicit canonical constructor is given
Vicente Romero
vicente.romero at oracle.com
Mon Jan 20 23:06:35 UTC 2020
Hi Gunnar
On 1/20/20 12:18 PM, Gunnar Morling wrote:
> Ah, yes, indeed! I'll track this issue then, thanks! Perhaps it would
> even make sense to have it fixed for JDK 14?
the issue has already being fixed in 15. Could you please try with 15 to
see double check that you can't reproduce the issue with jdk15?
>
> --Gunnar
Vicente
>
> Am Mo., 20. Jan. 2020 um 17:35 Uhr schrieb Jorn Vernee <jorn.vernee at oracle.com>:
>> Hi,
>>
>> I remember this issue coming up before. Looks like there was a fix
>> targeted at JDK 15: https://bugs.openjdk.java.net/browse/JDK-8236597
>>
>> Jorn
>>
>> On 20/01/2020 09:36, Gunnar Morling wrote:
>>> Thanks for your reply!
>>>
>>>> If a canonical ctor / accessor is explicitly specified, the annos on the declaration are used instead.
>>> That's where things are still unclear for me, it seems contradictory
>>> to "sounds like incorrect behavior to me" above. To make things more
>>> concrete, here's an example:
>>>
>>> public class RecordAnnos {
>>> public static void main(String... args) {
>>> System.out.println(Arrays.toString(Foo.class.getConstructors()[0].getParameters()[0].getAnnotations()));
>>> System.out.println(Arrays.toString(Bar.class.getConstructors()[0].getParameters()[0].getAnnotations()));
>>> }
>>>
>>> public static record Foo (@Deprecated String foo) {}
>>>
>>> public static record Bar (@Deprecated String bar) {
>>> public Bar {}
>>> }
>>> }
>>>
>>> Running this prints:
>>>
>>> java --enable-preview --source 14 RecordAnnos.java
>>> [@java.lang.Deprecated(forRemoval=false, since="")]
>>> []
>>>
>>> Whereas I hoped it'd print this:
>>>
>>> [@java.lang.Deprecated(forRemoval=false, since="")]
>>> [@java.lang.Deprecated(forRemoval=false, since="")]
>>>
>>> In case an explicit canonical constructor is declared without the
>>> formal parameter list, there's no way to specify any annotations on
>>> the parameters. So shouldn't those from the components be applied?
>>> With the current behaviour, if I want to declare any annotation for
>>> the constructor itself, I need to repeat all annotations from the
>>> components on the annotations of a fully manually implemented
>>> constructor:
>>>
>>> public static record Bar (@Deprecated String bar) {
>>> @Deprecated
>>> public Bar(@Deprecated String bar) {
>>> this.bar = bar;
>>> }
>>> }
>>>
>>> Note that @Deprecated is just used here to make the example
>>> self-contained; my actual use case is about Bean Validation constraint
>>> annotations.
>>>
>>> Thanks,
>>>
>>> --Gunnar
>>>
>>> Am Mo., 20. Jan. 2020 um 01:32 Uhr schrieb Brian Goetz <brian.goetz at oracle.com>:
>>>> This sounds like incorrect behavior to me. The way it should work is:
>>>>
>>>> - A declaration annotation is applicable to a record component if it has no @Target meta-anno, or its target includes one or more of PARAMETER, FIELD, METHOD, RECORD_COMPONENT.
>>>> - For _each_ of the applicable types present, the anno is pushed down to the corresponding _implicit_ { ctor parameter, field, accessor method, record component }.
>>>> - If multiple applicable types are present, it is pushed down to all of them.
>>>> - If a canonical ctor / accessor is explicitly specified, the annos on the declaration are used instead.
>>>>
>>>>
>>>>
>>>>
>>>> On 1/19/2020 4:14 PM, Gunnar Morling wrote:
>>>>
>>>> Hi,
>>>>
>>>> I'm observing the following behaviour around annotations on record
>>>> components, using JDK 14 b32. I'm putting an annotation to a record
>>>> component:
>>>>
>>>> public record Person(@NotNull String name) {}
>>>>
>>>> In this case the @NotNull annotation is propagated to the
>>>> corresponding parameter of the generated constructor, from where I can
>>>> obtain it using reflection. This is not the case though when I
>>>> explicitly declare the canonical constructor:
>>>>
>>>> public record Person(@NotNull String name) {
>>>> public Person {
>>>> // ...
>>>> }
>>>> }
>>>>
>>>> In this case the annotation isn't propagated, and it won't be
>>>> retrievable from that constructor's parameter via reflection.
>>>>
>>>> Is this behaviour intended or is it a bug actually? I lean towards the
>>>> latter, as I don't explicitly define the parameter in the constructor,
>>>> so I'd expect the annotations given on the component to still be
>>>> propagated.
>>>>
>>>> If it *is* intended, it'd make my use case a bit more complex, as I'd
>>>> want to be able to put other annotations to the canonical constructor
>>>> *itself*, while still getting all the component annotations propagated
>>>> to its parameters.
>>>>
>>>> Thanks a lot,
>>>>
>>>> --Gunnar
>>>>
>>>>
More information about the amber-dev
mailing list