【问题标题】:Java annotation: using a field value into another fieldJava注解:使用一个字段值到另一个字段中
【发布时间】:2017-05-24 00:17:55
【问题描述】:

我有如下注解类

public @interface Size {
  int min() default 1;
  int max() default 100;
  String message() default "Age between min - max";
}

这里默认message()我想要min()max()的默认值。在这里简单地写String message() default "Age between" + min() + "-" + max(); 是行不通的。有什么直接的方法吗?

编辑 1: 我也有个人课

public class Person {

  @Size(max = 10)
  private String name;

  @Size(min = 18, message = "Age can not be less than {min}")
  private int age;

  public Person(String s, int i) {
    this.name = s;
    this.age = i;
  }
}

现在,可以在此处设置 min()max() 值。因此,如果用户输入错误,则message() 将相应地成为打印机。

编辑 2: 正如@nicolas 想要的那样。这里是验证输入并打印错误消息的AnnonatedValidator 类。

public class AnnotatedValidator {

public static void validate(Person p, List<ValidationError> errors) {

    try {
        Field[] fields = p.getClass().getDeclaredFields();
        for(Field field : fields) {
            if(field.getType().equals(String.class)){
                field.setAccessible(true);
                String string = (String)field.get(p);

                Annotation[] annotationsName = field.getDeclaredAnnotations();
                for (Annotation annotation : annotationsName){
                    if (annotation instanceof Size){
                        Size size = (Size) annotation;
                        if (string.length() < size.min() || string.length() > size.max()) {
                            error(size, errors);
                        }
                    }
                }

            } else if (field.getType().equals(int.class)) {
                field.setAccessible(true);
                int integer = (Integer)field.get(p);

                Annotation[] annotationsAge = field.getDeclaredAnnotations();
                for (Annotation annotation : annotationsAge){
                    if (annotation instanceof Size){
                        Size size = (Size) annotation;
                        if (integer < size.min() || integer > size.max()) {
                            error(size,errors);
                        }
                    }
                }
            }
        }

    }catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

public static void print(List<ValidationError> errors) {
    for (int i = 0; i < errors.size(); i++){
        System.out.println("Errors: " + errors.get(i).getError());
    }
}

public static void error (Size size, List<ValidationError> errors) {
    String error = size.message();
    if (!error.equals(null)) {
        if (error.contains("min")) {
            error = error.replace("min", ""+size.min());
        }
        if (error.contains("max")){
            error = error.replace("max", ""+size.max());
        }
    }

    ValidationError v = new ValidationError();
    v.setError(error);
    errors.add(v);
}
}

ValidationError 是另一个只保存错误的类。

【问题讨论】:

  • 注解值应该是常量,不能调用min/max
  • 您应该在将打印消息的代码中管理它,因为如前所述,只有常量作为默认值
  • 如果您希望输入信息以改进它以获得预期结果,请显示显示消息的代码
  • 然后您应该使用{name} between {min} - {max} 作为默认消息,并将{min}{max} 分别替换为size.min()size.max(),并将{name} 替换为field.getName()
  • 我也是这样做的。我替换了最小值和最大值。

标签: java java-annotations


【解决方案1】:

不,String 类型的 default 值必须是常量表达式,如 Java Language Specification dictates

如果元素类型不相称,则为编译时错误 与元素值。元素类型T 与 元素值V 当且仅当以下条件之一为真:

  • [...]
  • T 不是数组类型,V 的类型是赋值兼容的 (§5.2)T,并且:
    • [...]
    • 如果T 是原始类型或String,则V 是常量表达式(第15.28 节)。

另一个注解元素的调用不是一个常量表达式。

您需要在管理注释使用的组件中处理此问题。将default 消息声明为某个特殊值。

String message() default "REPLACE_ME";

然后在构造消息时检查它。例如

Field field = ... // get 'age' field
Size size = field.getAnnotation(Size.class);
if (size != null) {
    String message = size.message();
    if (message.equals("REPLACE_ME")) {
        message = "Age between " + size.min() + " - " + size.max() + "."; 
    }
}
int min = size.min();
int max = size.max();
// if field is of type int
int value = field.getInt(instance);
if (value > max || value < min) {
    throw new ConstraintViolationException(message);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多