为@Annotation枚举分配一个值

发布于 2024-09-04 20:01:18 字数 1065 浏览 4 评论 0原文

我创建

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

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

然而,我的实际动机是在 @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.

有没有办法完成我希望完成的事情

I created

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

So that I could happily do something like this, which is perfectly legal syntax.

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

The reason being is, I am using enum to restrict the type of restriction that could be used, and be able to assign a value to that restriction.

However, my actual motivation is to use that restriction in an @annotation.

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

So that, I intended to do this:

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

to which, the compiler croaks

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

Is there a way to accomplish what I wish to accomplish

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

不离久伴 2024-09-11 20:01:18

你可以这样做:

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

You can do it like this:

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();
}
木落 2024-09-11 20:01:18

一部分来自编译错误,假设您能够做到这一点。那么您不认为在其他领域应用类似的注释会毁掉第一个领域吗?

我的意思是,

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

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

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

A part from compilation error, suppose you are able to do exactly this. Then don't you think applying the similar annotation on some other field will ruin the first one?

I mean to say,

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

The same instance will now have a different value, that is 32. So, the 64 will be lost, I believe. In case, they are processed on runtime sequentially, and at the time we change the value to 32, 64 one has already been processed. Then I suppose, we can change the setter method in the example given by mdma to something like below.

 static public Restriction setValue(int value) {    
      this.value = value;
      return this;
  }
不寐倦长更 2024-09-11 20:01:18

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

如果您将 Restriction 设为常规类,并具有私有构造函数和静态常量字段,则您可以使用方法链接来流畅地创建新实例:

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 类中。最好为不同的限制类型创建子类。

You can achieve what you want, but not with enums directly.

If you make Restriction a regular class, with private constructor and static constant fields, you can then use method chaining to create new instances fluently:

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

Which is then used exactly as your original code:

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

However, I'm concerned for the lack of OO here - if the restrictions have different behaviour or data needed for definition, then you will end up lumping everything in the Restrictions class. It will be better to create subclasses for the different restriction types.

£噩梦荏苒 2024-09-11 20:01:18

我选择 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 的答案保留在我的凹处以供将来使用。

I chose Abhin's as the answer to my question because it was the most comprehensive and it worked when I tried it out. However, I document here, in the form of an answer to my own question, what I actually did.

Renaming Abhin's terms, this would be how I would apply it (similar to Abhin's example):

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

Which I decided is too verbose. I could even abridge it to:

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

Which might be too incomprehensible and still to verbose. What I needed was something a programmer could specify quickly and comprehensively:

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

Therefore, I decided to use the quick and dirty:

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

Anyway, I am keeping Abhin's answer in my recesses for future use.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文