分配@Annotation枚举值

时间:2010-06-10 00:55:34

标签: java enums annotations

我创建了

enum Restrictions{
  none,
  enumeration,
  fractionDigits,
  length,
  maxExclusive,
  maxInclusive,
  maxLength,
  minExclusive,
  minInclusive,
  minLength,
  pattern,
  totalDigits,
  whiteSpace;

  public Restrictions setValue(int value){
    this.value = value;
    return this;
  }
  public int value;
}

所以我很乐意做这样的事情,这是完全合法的语法。

Restrictions r1 =
  Restrictions.maxLength.setValue(64);

原因是,我使用enum 来限制可以使用的限制类型,并且能够为该限制分配值

但是,我的实际动机是在@annotation中使用该限制。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
public @interface Presentable {
  Restrictions[] restrictions() default Restrictions.none;
}

所以,我打算这样做:

@Presentable(restrictions=Restrictions.maxLength.setValue(64))
public String userName;

,编译器呱呱叫

The value for annotation enum attribute must be an enum constant expression.

有没有办法完成我想要完成的任务

4 个答案:

答案 0 :(得分:26)

你可以这样做:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

class Person {    
    @Presentable({
        @Restriction(type = RestrictionType.LENGTH, value = 5),
        @Restriction(type = RestrictionType.FRACTION_DIGIT, value = 2)
    })
    public String name;
}

enum RestrictionType {
    NONE, LENGTH, FRACTION_DIGIT;
}

@Retention(RetentionPolicy.RUNTIME)
@interface Restriction {
    //The below fixes the compile error by changing type from String to RestrictionType
    RestrictionType type() default RestrictionType.NONE;
    int value() default 0;
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@interface Presentable {
  Restriction[] value();
}

答案 1 :(得分:3)

编译错误的一部分,假设你能够做到这一点。那么你不觉得在其他领域应用类似的注释会破坏第一个吗?

我的意思是说,

@Presentable(restrictions=Restrictions.maxLength.setValue(64))
public String userName;
@Presentable(restrictions=Restrictions.maxLength.setValue(32))
public String password;

相同的实例现在将具有不同的值,即32。因此,我相信64将会丢失。如果它们在运行时顺序处理,并且在我们将值更改为32时,已经处理了64个。然后我想,我们可以将setter给出的示例中的mdma方法更改为如下所示。

 static public Restriction setValue(int value) {    
      this.value = value;
      return this;
  }

答案 2 :(得分:2)

你可以实现你想要的,但不能直接使用枚举。

如果使用私有构造函数和静态常量字段使限制成为常规类,则可以使用方法链来流畅地创建新实例:

enum RestrictionType
{
   none,
   enumeration,
   maximumLength, 
   // ... etc.
}

class Restriction {
  static public final Restriction none = new Restriction(RestrictionType.none);
  static public final Restriction enumeration = new Restriction(RestrictionType.enumeration);
  static public final Restriction maximumLength = new Restriction(RestrictionType.maximumLength);

  ... etc

  RestrictionType type;
  int value;

  private Restriction(RestrictionType type)
  {
    this(type, 0);
  }
  private Restriction(RestrictionType type, int value)
  {
     this.type = type;
     this.value = value; // you don't really need
  }

  static public Restriction setValue(int value)
  {
      return new Restriction(type, value);
  }
}

然后将其用作原始代码:

@Presentable(restrictions=Restrictions.maxLength.setValue(64))
public String userName;

但是,我担心这里缺少OO - 如果限制具有不同的行为或定义所需的数据,那么最终会将所有内容都集中在Restrictions类中。最好为不同的限制类型创建子类。

答案 3 :(得分:1)

我选择Abhin作为我问题的答案,因为它是最全面的,当我试用它时它起作用了。但是,我在这里以对自己问题的回答的形式记录了我实际做了什么。

重命名Abhin的术语,这就是我应用它的方式(类似于Abhin的例子):

@Presentable({
@Restrictions(restriction=Restriction.FractionDigits, value="1"),
@Restrictions(restriction=Restriction.Length, value="10"),
    .....
})

我决定过于冗长。我甚至可以把它简化为:

@Presentable({
@R(r=R.FractionDigits, v="1"),
@R(r=R.Length, v="10"),
    .....
})

这可能太难以理解而且仍然冗长。我需要的是程序员可以快速全面地指定的东西:

@Presentable(sequence = 11, maxLen=64, readOnly=true)

因此,我决定使用快速而肮脏的东西:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
public @interface Presentable {
    int sequence();
    String caption() default "";
    int fractionDigits() default -1;
    int length() default -1;
    int maxLen() default -1;
    int minLen() default -1;
    int totalDigits() default -1;
    float maxVal() default -1;
    float minVal() default -1;
    String pattern() default "";
    String whiteSpace() default "";
    boolean readOnly() default false;
    boolean multiValue() default false;
    boolean hidden() default false;
    boolean isTest() default true;
}

无论如何,我将Abhin的答案保留在我的凹槽中以备将来使用。