Java 以下枚举验证器是线程安全的吗?

Java 以下枚举验证器是线程安全的吗?,java,generics,enums,bean-validation,Java,Generics,Enums,Bean Validation,我已经实现了一个枚举验证器。我想知道下面的代码是否是线程安全的?我有许多不同的枚举,我需要使用这个验证器。这会造成什么问题吗 @Documented @Constraint(validatedBy = StringEnumerationValidator.class) @Target({ElementType.FIELD,ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PA

我已经实现了一个枚举验证器。我想知道下面的代码是否是线程安全的?我有许多不同的枚举,我需要使用这个验证器。这会造成什么问题吗

@Documented
@Constraint(validatedBy = StringEnumerationValidator.class)
@Target({ElementType.FIELD,ElementType.ANNOTATION_TYPE,
ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@NotNull(message="Value must not be null.")
public @interface StringEnumeration {

    String message() default "{com.xxx.bean.validation.constraints.StringEnumeration.message}";
    Class<?>[] groups() default{};
    Class<? extends Payload>[] payload() default{};
    Class<? extends Enum<?>> enumClass();
}


public class StringEnumerationValidator implements
    ConstraintValidator<StringEnumeration, String> {

    private Set<String> AVAILABLE_ENUM_NAMES;

    public static Set<String> getNamesSet(Class<? extends Enum<?>> e){
        Enum<?>[] enums = e.getEnumConstants();
        String[] names = new String[enums.length];
        for (int i = 0; i < enums.length; i++) {
            names[i] = enums[i].name();
            System.out.println(enums.length);
            System.out.println(enums[i]);
        }
        Set<String> mySet = new HashSet<String>(Arrays.asList(names));
        return mySet;
    }

    @Override
    public void initialize(StringEnumeration stringEnumeration) {
        Class<? extends Enum<?>> enumSelected =   stringEnumeration.enumClass();
        AVAILABLE_ENUM_NAMES = getNamesSet(enumSelected);

    }
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null) {
        return true;
        }
        else {
            return AVAILABLE_ENUM_NAMES.contains(value);
        }

  }
@已记录
@约束(validatedBy=StringEnumerationValidator.class)
@目标({ElementType.FIELD,ElementType.ANNOTATION\u TYPE,
ElementType.METHOD,ElementType.CONSTRUCTOR,ElementType.PARAMETER})
@保留(RetentionPolicy.RUNTIME)
@NotNull(message=“Value不能为null。”)
public@interface字符串枚举{
String message()默认值“{com.xxx.bean.validation.constraints.StringEnumeration.message}”;
类[]组()默认值{};
类>枚举类();
}
公共类StringEnumerationValidator实现
约束校验器{
私有集可用的枚举名称;
公共静态集GetNameSet(类>e){
Enum[]enums=e.getEnumConstants();
字符串[]名称=新字符串[enums.length];
for(int i=0;ienumSelected=stringEnumeration.enumClass();
可用的\u枚举\u名称=GetNameset(enumSelected);
}
@凌驾
公共布尔值有效(字符串值、ConstraintValidatorContext上下文){
如果(值==null){
返回true;
}
否则{
返回可用的枚举名称。包含(值);
}
}
编辑:参考资料来源:


是和否。严格来说,它不是线程安全的,因为两个不同的线程可以同时调用
initialize
方法。此方法写入
AVAILABLE\u ENUM\u NAMES
变量,因此这两个线程可能会相互干扰

但是,如果确保在其他线程访问该实例之前,对每个实例只调用一次
initialize
,则该实例是线程安全的,因为
isValid
只读取集合,不修改集合

要确保仅完成一次初始化,应在构造函数中执行此操作:

public StringEnumeratorValidator(StringEnumeration stringEnumeration) {
    Class<? extends Enum<?>> enumSelected = stringEnumeration.enumClass();
    AVAILABLE_ENUM_NAMES = getNamesSet(enumSelected);
}
公共StringEnumeratorValidator(StringEnumeration StringEnumeration){
Class>enumSelected=stringEnumeration.enumClass();
可用的\u枚举\u名称=GetNameset(enumSelected);
}

并删除
初始化
方法。

由于您的
isValid
方法只执行读取操作,因此它是线程安全的,假设验证框架遵守在
初始化
完成之前不调用
isValid
的约定。更新的标记、固定的键入和删除的感谢。请添加到您所指的“旧帖子”。@Ram添加了源代码。