web-dev-qa-db-ja.com

@Annotation列挙型に値を割り当てる

私が作成しました

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.

私が達成したいことを達成する方法はありますか

16
Blessed Geek

あなたはこのようにそれを行うことができます:

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

コンパイルエラーの一部ですが、これを正確に実行できると仮定します。では、他のフィールドに同様の注釈を適用すると、最初のフィールドが台無しになると思いませんか?

つまり、

@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;
  }
3
Adeel Ansari

列挙型を直接使用することはできませんが、必要なことを達成できます。

プライベートコンストラクターと静的定数フィールドを使用して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クラスのすべてをひとまとめにすることになります。さまざまな制限タイプのサブクラスを作成します。

2
mdma

Abhin'sは最も包括的で、試してみるとうまくいったので、質問の答えとしてAbhin'sを選びました。しかし、私はここに、私自身の質問に対する答えの形で、私が実際にしたことを文書化します。

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

とにかく、私は将来の使用のために私の休憩所にアビンの答えを保持しています。

1
Blessed Geek