Как установить значение параметра пользовательской аннотации [duplicate]

Предполагая, что value является double, вы можете сделать:

(double)Math.round(value * 100000d) / 100000d

Это для 5-значной точности. Число нулей указывает количество десятичных знаков.

42
задан Thomas Jung 7 September 2009 в 19:52
поделиться

5 ответов

Нет, нет обходного пути.

43
ответ дан Thomas Jung 23 August 2018 в 02:18
поделиться
  • 1
    но почему? Зачем??? – Jens Schauder 27 March 2015 в 13:49
  • 2
    @JensSchauder Аннотации обрабатываются во время компиляции, поэтому даже до того, как код когда-либо запускается. Таким образом, массив AB еще не существует. – Stijn de Witt 7 September 2015 в 19:06
  • 3
    если компилятор ожидает «Инициализатор массива», для передачи в аннотацию, объявление постоянной времени компиляции, например private static final String[] AB = { ... };. понятно, что обработка аннотации происходит до фактической компиляции, но тогда сообщение об ошибке неточно. – asgs 2 May 2018 в 09:16

Почему бы не сделать значения аннотации enum, которые являются ключами к фактическим значениям данных, которые вы хотите?

, например

enum InfoKeys
{
 A("a"),
 B("b"),
 AB(new String[] { "a", "b" }),

 InfoKeys(Object data) { this.data = data; }
 private Object data;
}

@SomeAnnotation (values = InfoKeys.AB)

Это может быть улучшено для безопасности типа, но вы получите эту идею.

13
ответ дан amarillion 23 August 2018 в 02:18
поделиться
  • 1
    +1 Хорошее мышление. Пример, который был скомпилирован, был бы еще приятнее ;-) – skaffman 7 September 2009 в 08:26
  • 2
    Хорошая идея. Это нормально, если вы можете изменить аннотацию. Вы должны использовать @interface SomeAnnotation {InfoKeys values ​​(); }. К сожалению, он не может изменить сам тип аннотации. – Thomas Jung 7 September 2009 в 08:47
  • 3
    Изменение типа аннотации ограничило бы использование значений этого перечисления. Это относится к большинству случаев использования. – Thomas Jung 7 September 2009 в 08:51
  • 4
  • 5
    У вас есть аннотация. Использование этой аннотации не должно быть избыточным. Идеальное решение будет состоять в том, чтобы поддерживать полное и частичное повторное использование «экземпляра аннотации». Полное повторное использование: @x = @SomeAnnotation (...); @x m (); @x y () ;. Частичное повторное использование: @SomeAnnotation (childAnnotation = @ x) m (). Ссылка на значения аннотации является компромиссом, а не целью. – Thomas Jung 7 September 2009 в 09:16

Хотя невозможно передать массив непосредственно в качестве значения параметра аннотации, есть способ эффективно получить подобное поведение (в зависимости от того, как вы планируете использовать свои аннотации, это может не работать для каждого варианта использования).

Вот пример - допустим, у нас есть класс InternetServer и он имеет свойство hostname. Мы хотели бы использовать регулярную проверку Java, чтобы гарантировать, что ни один объект не имеет «зарезервированное» имя хоста. Мы можем (несколько продуманно) передать массив зарезервированных имен хостов в аннотацию, которая обрабатывает проверку имени хоста.

caveat- с Java Validation, было бы более привычно использовать «полезную нагрузку» для передачи в таком виде данные. Я хотел, чтобы этот пример был более общим, поэтому я использовал собственный класс интерфейса.

// InternetServer.java -- an example class that passes an array as an annotation value
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.Pattern;

public class InternetServer {

    // These are reserved names, we don't want anyone naming their InternetServer one of these
    private static final String[] RESERVED_NAMES = {
        "www", "wwws", "http", "https",
    };

    public class ReservedHostnames implements ReservedWords {
        // We return a constant here but could do a DB lookup, some calculation, or whatever
        // and decide what to return at run-time when the annotation is processed.
        // Beware: if this method bombs, you're going to get nasty exceptions that will
        // kill any threads that try to load any code with annotations that reference this.
        @Override public String[] getReservedWords() { return RESERVED_NAMES; }
    }

    @Pattern(regexp = "[A-Za-z0-9]{3,}", message = "error.hostname.invalid")
    @NotReservedWord(reserved=ReservedHostnames.class, message="error.hostname.reserved")
    @Getter @Setter private String hostname;
}

// NotReservedWord.java -- the annotation class
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target({FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy=ReservedWordValidator.class)
@Documented
public @interface NotReservedWord {

    Class<? extends ReservedWords> reserved ();

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    String message() default "{err.reservedWord}";

}

// ReservedWords.java -- the interface referenced in the annotation class
public interface ReservedWords {
    public String[] getReservedWords ();
}

// ReservedWordValidator.java -- implements the validation logic
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ReservedWordValidator implements ConstraintValidator<NotReservedWord, Object> {

    private Class<? extends ReservedWords> reserved;

    @Override
    public void initialize(NotReservedWord constraintAnnotation) {
        reserved = constraintAnnotation.reserved();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        if (value == null) return true;
        final String[] words = getReservedWords();
        for (String word : words) {
            if (value.equals(word)) return false;
        }
        return true;
    }

    private Map<Class, String[]> cache = new ConcurrentHashMap<>();

    private String[] getReservedWords() {
        String[] words = cache.get(reserved);
        if (words == null) {
            try {
                words = reserved.newInstance().getReservedWords();
            } catch (Exception e) {
                throw new IllegalStateException("Error instantiating ReservedWords class ("+reserved.getName()+"): "+e, e);
            }
            cache.put(reserved, words);
        }
        return words;
    }
}
2
ответ дан cobbzilla 23 August 2018 в 02:18
поделиться

Это потому, что элементы массива могут быть изменены во время выполнения (Info.AB[0] = "c";), в то время как значения аннотации являются постоянными после времени компиляции.

Учитывая это, кто-то неизбежно будет смущен, когда они попытаются изменить элемент Info.AB и ожидаем изменения значения аннотации (это не будет). И если значение аннотации разрешено изменять во время выполнения, оно будет отличаться от значения, используемого во время компиляции. Представьте себе путаницу!

(где путаница здесь означает, что есть ошибка, которую кто-то может находить и тратить часы на отладку.)

0
ответ дан Michael Deardeuff 23 August 2018 в 02:18
поделиться
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Handler {

    enum MessageType { MESSAGE, OBJECT };

    String value() default "";

    MessageType type() default MessageType.MESSAGE;

}
-1
ответ дан Shakeel Kadam 23 August 2018 в 02:18
поделиться
  • 1
    Можете ли вы добавить объяснение коду? – Peanut 4 August 2015 в 13:20
  • 2
    Это плохой ответ, даже если он правильный. Добавление объяснения значительно улучшило бы его (как сказал @Peanut) – mccainz 4 August 2015 в 13:33
Другие вопросы по тегам:

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