views:

130

answers:

4

Guys is there a way to pass a Annotation as a direct parameter (rather by doing all the reflection overhead)? For example in the following code, I have a annotation Number that holds a int value, I want to pass as a parameter to the addImpl method, how can I do that (other than by reflection)?

Code Snippet:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
public @interface Number {
    int value();
}

public void add(int x2) {
    addImpl(@Number(value = 10) lol, x2);
}

public void addImpl(Number a, int b) {
    System.out.println(a.value() + b);
}

public static void main(String[] args) {
    new TestClass().add(3);
}
+4  A: 

Yes, you can pass around annotations like this (just as if they were normal interfaces).

The only thing you can't do is to create instances of that interface at runtime. You can only take existing annotations and pass them around.

import java.lang.annotation.*;

public class Example {

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public static @interface Number {
        int value();
    }

    @Number(value = 42)
    public int adder(final int b) throws SecurityException, NoSuchMethodException {
        Number number = getClass().getMethod("adder", int.class).getAnnotation(Number.class);
        return addImpl(number, b);
    }

    public int addImpl(final Number a, final int b) {
        return a.value() + b;
    }

    public static void main(final String[] args) throws SecurityException, NoSuchMethodException {
        System.out.println(new Example().adder(0));
    }
}
Joachim Sauer
Okaaay - are there some real-world use cases for this?
Andreas_D
@Andreas_D: sure, wherever you react on some annotation you can easily refactor the code to do its job in several methods (or even classes) and being able to pass around the annotation can be very useful.
Joachim Sauer
+2  A: 

To the best of my knowledge, there's no such thing as an "annotation literal" as you want to use it in your add implementation.

I think the closest thing to this would be to declare the method to take a parameter of type java.lang.annotation.Annotation - but then you'd still need to obtain those instances via reflection from the class/method objects.

Andrzej Doyle
+2  A: 

You can do it like:

public void add(int x2) {
    addImpl(new Number() {

        @Override
        public int value() {
            return 10;
        }

        @Override
        public Class<? extends Annotation> annotationType() {
            return Number.class;
        }
    }, x2);
}

Since Number is basically an interface, you have to create an instance of an anonymous class that implements that interface, and pass that to the method.

Although why you want to do this is beyond me. If you need to pass a value to something, you should really use a class.

Andrei Fierbinteanu
The number is just a sample :3
Marcos Roriz
A: 

Number is also a good old interface, you can implement a concrete class.

Guys, this is useful. While a module mostly deals with annotations which are fixed at compile time, sometimes we need to feed it other info obtained at runtime from other sources(like xml, gush!) We can over-architect the thing, or we can simply creat a runtime object of the annotaion type.

irreputable
Implementing annotation interfaces in your own classes is at least a code smell.
Joachim Sauer
the smell of mastery is good.
irreputable