I'm creating an custom annotation with parameters. Parameters I want to use are enums that implement an interface. There are few enums that are candidates to b used as this annotation's parameter. Here are some code examples:
Interface:
public interface MyInterface {
String getSomething();
int getMore();
}
Enum example:
public enum MyEnum implements MyInterface {
VAL1("some1", 1),
VAL2("2val", 22);
private String something;
private int more;
private MyEnum(String something, int more) {
this.something = something;
this.more = more;
}
public String getSomething() {
return something;
}
public int getMore() {
return more;
}
}
I want to implement an annotation with parameter that can be retrieved as multiple MyInterface values. Let's say annotation looks like this:
@MyAnnotation(MyEnum.class)
or
@MyAnnotation(MyEnum.values())
So I can further retrieve it and pass it to a method that accepts Collection parameter.
How do I implement an annotation with a parameter so I can retrieve all values of enum as MyInterface type?
I was trying to do it like this:
public @interface MyAnnotation {
Class<? extends Enum<?> & MyInterface> myValues();
}
So I could do:
Collection<MyInterface> desired = Arrays.asList(... .getAnnotation().myValues().enumValues());
but this syntax is invalid.
You can't use union types in an annotation member, so you'll have to give up on that idea.
But frame challenge: why do you even care that the implementer has to be an enum?
What I assume you care about is that something can give you a finite set of implementations. An enum is one way to achieve that, but why be overly restrictive if someone wants to give you a list of values some other way?
I'd add a new interface which can provide a collection of values.
interface MyInterfaceValueSource {
List<MyInterface> values();
}
The enum gets a very simple implementation that just calls MyEnum.values()
.
class MyEnumValueSource implements MyInterfaceValueSource {
@Override
public List<MyInterface> values() {
return Arrays.asList(MyEnum.values());
}
}
Your annotation can then be altered to accept one of those
@interface MyAnnotation {
Class<? extends MyInterfaceValueSource> value();
}
and example of its usage would be
@MyAnnotation(MyEnumValueSource.class)
Now if someone wants to provide a list of values but not implement it as an enum, they have the flexibility to do that.
class ExampleValueSource implements MyInterfaceValueSource {
@Override
public List<MyInterface> values() {
return Arrays.asList(
new MyInterfaceOne(), new MyInterfaceTwo()
);
}
}