有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在枚举中存储类引用?

因此,在我的work automation tests项目中,我有一个描述AdminTool中项目配置参数的枚举:

@Getter
public enum AdminParametersEnum {

    SUPPORTED_SPORTS("SupportedSports", ParamTypeEnum.JSON),
    MAPPING_SERVICE_URL("MappingService.URL", ParamTypeEnum.STRING),
    MAPPING_SERVICE_ENABLE("MappingService.enable", ParamTypeEnum.BOOLEAN);

    private final String key;
    private final ParamTypeEnum valueType;

    AdminParametersEnum(String key, ParamTypeEnum valueType) {
        this.key = key;
        this.valueType = valueType;
    }

    @Getter
    public enum ParamTypeEnum {

        JSON("JSON"),
        STRING("String"),
        NUMBER("Number"),
        BOOLEAN("Boolean");

        private String type;

        ParamTypeEnum(String type) {
            this.type = type;
        }
    }
}

还有一个AdminService_parameters管理_DataProvider类,用于以某个类的对象的形式获取这些参数的值,它描述了该参数的响应模型(请参阅“getSupportedSports()”方法):

public class AdminService_ParametersManagement_DataProvider extends AdminService_ParametersManagement_Endpoint {

    private AdminConfigurationParameter getByKey(AdminParametersEnum key) {
        return getFirstOrNull(getAll().getByFilter(parameter -> parameter.getKey().equalsIgnoreCase(key.getKey())));
    }

    private <T> T getParameter(AdminParametersEnum paramName, Class<T> paramValueToBeCastedTo) {
        AdminConfigurationParameter parameter = getByKey(paramName);

        return isNull(parameter) ?
                null :
                toObject(parameter.getValue().toString(), paramValueToBeCastedTo);
    }

    public SupportedSportsParamValueModel getSupportedSports() {
        return getParameter(SUPPORTED_SPORTS, SupportedSportsParamValueModel.class);
    }
}

如您所见,“getParameter”方法中有“paramValueToBeCastedTo”参数,因此响应中的参数值在“toObject”方法中转换为所需的对象模型:

public static <T> T toObject(@NonNull String json, @NonNull Class<T> clazz) {
        if (json == null) {
            throw new NullPointerException("json is marked @NonNull but is null");
        } else if (clazz == null) {
            throw new NullPointerException("clazz is marked @NonNull but is null");
        } else {
            return getGson(false).fromJson(json, clazz);
        }
}

但在未来,可能会有很多参数有自己的响应模型,现在需要创建单独的方法来获取每个参数,如下所示:

 public SupportedSportsParamValueModel getSupportedSports() {
            return getParameter(SUPPORTED_SPORTS, SupportedSportsParamValueModel.class);
        }

所以我的问题是——是否有可能以某种方式将“paramValueToBeCastedTo”类引用存储在“AdminParametersEnum”枚举中? 例如,向该枚举中再添加一个字段:

Class<T> paramValueToBeCastedTo;

然后枚举值将如下所示:

SUPPORTED_SPORTS("SupportedSports", ParamTypeEnum.JSON, SupportedSportsParamValueModel.class)

因此,我有一种方法来获取任何参数

因为不需要分别为每个参数传递响应对象模型

因为它已经存储在enum中,如下所示:

public <T> T getParameter(AdminParametersEnum paramName) {
        AdminConfigurationParameter parameter = getByKey(paramName);

        return isNull(parameter) ?
                null :
                toObject(parameter.getValue().toString(), paramName.getParamValueToBeCastedTo());
    }

我试图在代码中实现这一点,但运气不好,我甚至无法在enum中定义此字段:

Class<T> paramValueToBeCastedTo;

所以,你能解释一下,我是否可以用和我描述的类似的方式,或者用不同的方法,以其他方式来做吗

我只需要为每个管理参数存储响应模型类引用


共 (1) 个答案

  1. # 1 楼答案

    首先,你应该意识到,有了这样的签名:

    private <T> T getParameter(AdminParametersEnum paramName)
    

    推断类型参数T的唯一方法是从返回类型。enum参数完全不能用于类型推断。不能说“T必须与与paramName参数关联的Class的类型相同”。这意味着允许调用方(在编译时)执行以下操作:

    // This will throw an exception at runtime
    Integer definitelyTheWrongType = getParameter(AdminParametersEnum. MAPPING_SERVICE_ENABLE);
    

    现在,完成了免责声明后,将字段添加到枚举的方法是使用Class<?>

    private Class<?> paramValueToBeCastedTo;
    

    更改枚举常量和构造函数,并为其添加一个getter。然后您可以将getParameters重写为:

    private <T> T getParameter(AdminParametersEnum paramName) {
        AdminConfigurationParameter parameter = getByKey(paramName);
    
        return isNull(parameter) ?
                null :
                toObject(parameter.getValue().toString(), 
                (Class<T>)paramName.getParamValueToBeCastedTo());
    }
    

    请注意未选中的对Class<T>的强制转换。正如我在开头提到的,这是由于这种方法固有的不安全性