21

This question is now over 3 years old and specifically addressed Java 8, with the accepted answer also citing the Java SE 8 Final Specification.

I would be interested if something regarding this question will change in Java 9: Is there any way to annotate a lambda expression similar to annotating a corresponding anonymous class?


Example:

Annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface MyTypeAnnotation {
    public String value();
}

Working annotation of anonymous class:

Consumer<String> consumer = new @MyTypeAnnotation("Hello ") Consumer<String>() {
    @Override
    public void accept(String str) {
        System.out.println(str);
    }
};

Annotating a lamba expression, currently not working in Java 8:

Consumer<String> myAnnotatedConsumer = @MyTypeAnnotation("Hello") (p -> System.out.println(p));
Markus Weninger
  • 11,931
  • 7
  • 64
  • 137
  • One important difference between these two constructs is that a anonymous class still is a declaration of a class. A lambda expression don't create a new class (or not necessarily, if it does that is an implementation detail). I have the impression that annotations are only ever allowed on *declarations*. Are annotations ever allowed on *expressions*? – Lii Jul 27 '17 at 13:27

3 Answers3

18

The existence of a Stack Overflow question is not sufficient to indicate that such a feature is planned, not even that someone is ever considering it.

If you look at the list of JEPs, you will see that there is no such JEP, not even in a draft state, suggesting such a feature.

Also, if you look at the current state of Java 9’s LambdaMetafactory, you will see that no change has been made to support passing the meta information that would be necessary to generate a runtime class with recorded annotation data.

There seems to be some desire to add plenty of meta-information to what actually should be a small piece of throw-away code, but I doubt that the language designer will follow it. Lambda expressions are meant to define a function which encapsulates behavior, not an alternative way to describe an anonymous class. The long term evolution will rather lead to lambda expression implementations which are even less of an ordinary class.

Pang
  • 9,564
  • 146
  • 81
  • 122
Holger
  • 285,553
  • 42
  • 434
  • 765
  • 2
    `... are even less of an ordinary class ` I can't wait that to happen and the changes that would be required for that – Eugene Jun 20 '17 at 20:21
  • Lambdas don't preserve their generics parameters either, which makes some framework use cases relying on reflection hard or impossible. Annotations could have helped, so not having either is unfortunate. But I see the point about lambdas not being class-like. – Michael Böckling Jun 30 '20 at 21:06
  • 1
    @MichaelBöckling mind that the question’s example annotates a *creation site* (the `new` operator’s type), which isn’t available via Reflection anyway. When you annotate the parameters of a lambda expression (or its parameter types), the annotations should be available, but you have to look into the creator’s class for the corresponding synthetic method, instead of the runtime generated class. Further, in my tests, only Eclipse produced reliable results, `javac` failed badly. Another obstacle is getting from a particular instance of a functional interface to the corresponding target method. – Holger Jul 01 '20 at 09:00
  • `> getting from a particular instance of a functional interface to the corresponding target method` Is that even possible with a stable API? If so, this might solve a problem that I have right now. – Michael Böckling Jul 01 '20 at 13:05
  • 1
    @MichaelBöckling that’s [an old issue](https://stackoverflow.com/q/31178103/2711488). In short, there is no API for that (that’s why I called it an obsactle). The only in-language solution is to enforce serializable functions, as they have a persistent representation that names the target method. Otherwise, I’d rather use bytecode instrumentation. – Holger Jul 01 '20 at 13:33
9

it's interesting that they do annotate the inner class that "represents" the lambda expression in InnerClassLambdaMetafactory.spinInnerClass via :

 mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true)

But that is annotating a class obviously, not a lambda per-se.

Annotating a lambda would require changes to the invokedynamic and implicitly the LambdaMetafactory as far as I can see - and what would happen when invokedynamic would not create a class for the lambda, but something else, what would happen to those annotations?

Eugene
  • 117,005
  • 15
  • 201
  • 306
7

According to the What's new in Oracle JDK 9 page, No. This has not changed in Java 9.

Of course, that is not definitive, but the JLS for Java 9 has not been released yet.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216