10

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

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

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

Object[] 也不起作用。

有没有办法做我想做的事?

4

5 回答 5

6

产生错误是因为您不能将接口用作注释值(将其更改为Comparable,您将得到相同的错误)。从JLS

如果在注解类型中声明的方法的返回类型是以下类型之一以外的任何类型,则这是编译时错误:基本类型之一StringClass以及Class对枚举类型、注解类型或上述类型之一的数组。如果在注解类型中声明的任何方法的签名与在 class或 interface 中声明的任何publicor方法的签名等效,这也是编译时错误。protectedObjectannotation.Annotation

恐怕我不知道一个好的解决方法,但现在至少您知道为什么会出现错误。

于 2009-03-24T20:54:30.833 回答
4

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

单个注释类型的实例数组

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

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

一组注释类型而不是实例

如果您不需要在各个注释上指定任何参数,则可以只使用它们的类对象而不是实例。

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

但是在大多数情况下,枚举当然也可以解决问题。

使用多个数组

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

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

为每个成员指定一个默认值可以只为您需要的类型指定数组。

于 2013-03-18T10:54:18.083 回答
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{
    // ...
}
于 2009-03-24T23:47:46.423 回答
1

你可以做:

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

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

于 2009-03-24T20:49:50.157 回答
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 子句”注释中提取可能的有效配置。在这种情况下,我还将原型类用作逻辑 AND 分组,并将类数组用作逻辑 OR。

于 2014-07-09T04:42:06.153 回答