包含其他注释的注释成员?

时间:2009-03-24 20:44:07

标签: java annotations

我想创建一个自定义注释(使用Java),它将接受其他注释作为参数,如:

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

但是这会导致编译器错误“注释成员的类型无效”。

对象[]也不起作用。

有办法做我想做的事吗?

5 个答案:

答案 0 :(得分:5)

产生错误是因为您无法将接口用作注释值(将其更改为Comparable并且您将获得相同的错误)。来自JLS

  

如果在注释类型中声明的方法的返回类型是除以下之一之外的任何类型,则是编译时错误:其中一种基本类型StringClass和任何Class的调用,枚举类型,注释类型或前述类型之一的数组。如果在注释类型中声明的任何方法具有覆盖的签名等同于在类public中声明的任何protectedObject方法的签名,那么它也是编译时错误界面annotation.Annotation

我担心我不知道一个好的解决方法,但现在至少你知道为什么会得到错误。

答案 1 :(得分:2)

我自己特此提出针对特定问题的解决方法:

嗯,我想做的就是这样:

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

建议的解决方法:

使用无参数构造函数(稍后将由您自己的注释处理器调用)以下列方式定义一个类:

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)
                )
            )
        );
    }
}

用法:

@Contract(MyContract.class)
class MyClass{
    // ...
}

答案 2 :(得分:2)

根据您想要指定其他注释的原因,有多种解决方案:

单个注释类型的实例数组

可能不是您在问题中的意思,但如果您想指定单个注释类型的多个实例,那肯定是可能的:

public @interface Test {
    SomeAnnotation[] value();
}

注释类型数组而不是实例

如果您不需要在单个注释上指定任何参数,则只需使用其类对象而不是实例。

public @interface Test {
    Class<? extends Annotation>[] value();
}

但是在大​​多数情况下,枚举当然也会成功。

使用多个数组

如果您要使用的可能注释类型集是有限的,则可以为每个注释类型创建一个单独的参数。

public @interface Test {
    SomeAnnotation[] somes() default { };
    ThisAnnotation[] thiss() default { };
    ThatAnnotation[] thats() default { };
}

为每个成员提供默认值使得只能为您需要的类型指定数组。

答案 3 :(得分:1)

你可以这样做:

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

不确定这是否有帮助,但是。 。 。

答案 4 :(得分:0)

我刚刚遇到了这个问题,但是(受@ivan_ivanovich_ivanoff启发)我发现了一种方法来指定一组 任何 注释组合作为注释成员:使用原型/模板类。

在这个例子中,我定义了一个 WhereOr (即我的模型注释的“where子句”),我需要包含任意Spring元注释(如@Qualifier元注释)。

这里的次要(?)缺陷是强制解除引用,它将where子句的实现与它描述的具体类型分开。

@Target({})
@Retention(RetentionPolicy.RUNTIME)
public @interface WhereOr {
    Class<?>[] value() default {};
}

@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonModel {
    Class<?> value();
    WhereOr where() default @WhereOr;
}

public class Prototypes {
    @Qualifier("myContext")
    @PreAuthorize("hasRole('ROLE_ADMINISTRATOR')")
    public static class ExampleAnd {
    }
}

@JsonModel(
        value = MusicLibrary.class,
        where = @WhereOr(Prototypes.ExampleAnd.class)
)
public interface JsonMusicLibrary {
    @JsonIgnore
    int getMajorVersion();
    // ...
}

我将以编程方式从“where子句”注释中提取可能的有效配置。在这种情况下,我还将prototypes类用作逻辑AND分组,将类数组用作逻辑OR。