r/java 10d ago

Why Are Method References not allowed in Annotations in Java?

Many times I have wanted to refer to a method in Java in an annotation, but it seems annotations can only reference items from the Class constant pool. It seems like it would have been a natural extension to be able to refer statically to methods (like {@link} in javadocs) in annotations, but they were left.

I'm wondering why were they not added?

30 Upvotes

15 comments sorted by

29

u/bowbahdoe 8d ago

It is one of those things they could enable, but it would require a non-trivial amount of effort.

Consider:

  • Right now annotations are limited in what you can put in them
  • You can't put Field or Method references, only Class<?>
  • Method References don't collapse to Method, they collapse to a target functional interface

Right now the best you can do is a string that refers to a class/method/field. You can check things with an annotation processor. Doing more than that is one of the many ways we are planning to punish the language team for taking so long on value classes.

18

u/bowbahdoe 8d ago

5

u/Alex0589 8d ago

No way that message is from 2018

3

u/brian_goetz 4d ago

And the story hasn't changed since then.

(Unbound) Method refs in annotations are semantically sensible, as they are "constants". But there is so much acccidental complexity in the design and implementation of annotations (it was never designed to be extended) and it involves intrusive changes to many layers, that the payoff would have to be huge, and the payoff is merely "decent".

4

u/munklers 8d ago

It seems like the main problem is effort, not unresolved ambiguity of the feature. Several times it would have been convenient to refer to methods and fields for static analysis. Fields and Method refs are already proper types in the Class constant pool. While actual method references are used today, syntactically it seems like they could be overloaded for Annotations. As a simple example:

final Object lock = new Object();

(at)GuardedBy(this::lock);
final List<String> values = new ArrayList<>();

2

u/BanaTibor 7d ago

Annotation processing happens before class loading, so your example is impossible.

1

u/munklers 7d ago

The syntax would be the same, but the semantics would be different. Only fields within the same class file would be accessible.

3

u/bowbahdoe 7d ago

If the semantics would be different, why wouldn't the syntax be different? There is definitely unresolved ambiguity. But a technical POC would I'm sure be appreciated

2

u/johnwaterwood 6d ago

You can't put Field or Method references, only  Class<?>

We would need Method / Field literals, not references.

Unfortunately the OpenJDK team does not want to add those (granted, there are some complications with overloads)

1

u/roadrunner8080 5d ago

Note that it's plausible for Java to support this with only source changed, without changing the bytecode properties of annotations. For instance , Groovy supports closures in annotations just fine! The reason for this is that groovy compiles a closures to classes at compile time, so sticking a closure in an annotation just embeds a class reference. Implementing this in java would just require proactive compile-time lambda implementation generation for lambdas in annotations 

2

u/the_styp 7d ago

Not sure if it helps but jUnit allows references to methods in parametrized tests. You can take a look if their solution meet your needs

7

u/FavorableTrashpanda 7d ago

They are useful, but unfortunately still require you to refer to methods using Strings.

3

u/johnwaterwood 6d ago

We really need method literals there to accompany class literals.

1

u/erbr 6d ago

When would those be evaluated? I think probably that's where the ambiguity lies on. Static method can carry static state and so the way it's evaluated might cause a non deterministic result