Присвоение @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);

Так как причина, я использую перечисление для ограничения типа ограничения, которое могло использоваться, и смочь присвоить значение тому ограничению.

Однако моя фактическая мотивация должна использовать то ограничение в @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 10 June 2010 в 00:55
поделиться

4 ответа

Вы можете сделать это так:

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();
}
27
ответ дан 30 November 2019 в 17:14
поделиться

Часть от ошибки компиляции, предположим, что вы способны сделать именно это. Тогда не думаете ли вы, что применение аналогичной аннотации к какому-то другому полю разрушит первое?

То есть,

@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
ответ дан 30 November 2019 в 17:14
поделиться

Вы можете добиться того, чего хотите, но не напрямую с помощью перечислений.

Если вы сделаете 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;

Однако я Меня беспокоит отсутствие здесь объектно-ориентированного подхода - если ограничения имеют другое поведение или данные, необходимые для определения, тогда вы в конечном итоге объедините все в класс Restrictions. Лучше создать подклассы для разных типов ограничений.

2
ответ дан 30 November 2019 в 17:14
поделиться

Я выбрал ответ Абина в качестве ответа на свой вопрос, потому что он был наиболее исчерпывающим и работал, когда я его пробовал. Однако я документирую здесь в форме ответа на свой вопрос, что я на самом деле сделал.

Переименовывая термины Абхина, я бы применил их следующим образом (аналогично примеру Абхина):

@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
ответ дан 30 November 2019 в 17:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: