views:

414

answers:

3

Hello!

I want to create a custom annotation (using Java) which would accept other annotations as parameter, something like:

public @interface ExclusiveOr {
    Annotation[] value();
}

But this causes compiler error "invalid type for annotation member".

Object[] also doesn't work.

Is there a way to do what I want?

+1  A: 

You can do:

Class<? extends Annotation>[] value();

Not sure if that helps, but . . .

Todd R
Sorry, it doesn't. I need instances of annotations, not types.
ivan_ivanovich_ivanoff
+2  A: 

The error is produced because you can't use interfaces as annotation values (change it to Comparable and you'll get the same error). From the JLS:

It is a compile-time error if the return type of a method declared in an annotation type is any type other than one of the following: one of the primitive types, String, Class and any invocation of Class, an enum type, an annotation type, or an array of one of the preceding types. It is also a compile-time error if any method declared in an annotation type has a signature that is override-equivalent to that of any public or protected method declared in class Object or in the interface annotation.Annotation.

I'm afraid I don't know of a good workaround, but now at least you know why you get the error.

Michael Myers
+1  A: 

I myself hereby propose a workaround for the given problem:

Well, what I wanted to make possible was something like that:

@Contract({
    @ExclusiveOr({
        @IsType(IAtomicType.class),
        @Or({
            @IsType(IListType.class),
            @IsType(ISetType.class)
        })
    })
})

Proposed workaround:

Define a class with parameter-less constructor (which will be called by your own annotation processor later) in following way:

final class MyContract extends Contract{
    // parameter-less ctor will be handeled by annotation processor
    public MyContract(){
        super(
            new ExclusiveOr(
                new IsType(IAtomicType.class),
                new Or(
                    new IsType(IListType.class),
                    new IsType(ISetType.class)
                )
            )
        );
    }
}

usage:

@Contract(MyContract.class)
class MyClass{
    // ...
}
ivan_ivanovich_ivanoff
Why do you need a workaround for that?
Ingo
Because annotations do not accept any type of parameters.Java allows only to specify an array of ONE CERTAIN type of annotation (not any type, what I need).
ivan_ivanovich_ivanoff