Java 编译器能否通过泛型方法验证对象的泛型类型?

Java 编译器能否通过泛型方法验证对象的泛型类型?,java,generics,enums,Java,Generics,Enums,首先,为这个糟糕的标题感到抱歉。我不知道如何用几句话来描述这个问题(也许不是很多) 我正在重构我们系统中的一些设置,使之更加抽象。当前解决方案在数据库中有多个表,每个设置区域一个表。为了添加一个新的设置,您需要扩展模式、hibernate类、所有传输对象类、getter/setter等。我觉得这违反了OCP(开-闭原则),因此需要重构 我花了一些时间想出了如何实现这种抽象的想法。到目前为止,我最喜欢的想法如下: public class SettingDefinition<T> {

首先,为这个糟糕的标题感到抱歉。我不知道如何用几句话来描述这个问题(也许不是很多)

我正在重构我们系统中的一些设置,使之更加抽象。当前解决方案在数据库中有多个表,每个设置区域一个表。为了添加一个新的设置,您需要扩展模式、hibernate类、所有传输对象类、getter/setter等。我觉得这违反了OCP(开-闭原则),因此需要重构

我花了一些时间想出了如何实现这种抽象的想法。到目前为止,我最喜欢的想法如下:

public class SettingDefinition<T> {
    private String name;
    private T defaultValue;

    public SettingDefinition(String name, T defaultValue) {
            this.name = name;
            this.defaultValue = defaultValue;
    }

    public String getName() {
            return name;
    }

    public T getDefaultValue() {
            return defaultValue;
    }
}
  • 每个设置区域1个枚举
  • 每个设置1个枚举值
  • 每个设置都是一个使用泛型类型的
    设置定义
  • 设置服务
    正在使用泛型类型的静态get/set方法
例如,设置区域可以是:

public enum SettingsABC{
    A(new SettingDefinition<Integer>("A", 123)),
    B(new SettingDefinition<String>("B", "Hello")),
    C(new SettingDefinition<Boolean>("C", false));

    private SettingDefinition settingDefinition;

    SettingsABC(SettingDefinition settingDefinition) {
            this.settingDefinition = settingDefinition;
    }

    public SettingDefinition getDefinition() {
            return settingDefinition;
    }
}
获取/设置值的服务将是:

public class SettingsService {
    public static <T> T getSetting(SettingDefinition setting) {
            // hit db to read
            // return value
    }

    public static <T> void setSetting(SettingDefinition setting, T value) {
            // hit db to write
    }
}
我的问题是,我无法在
SettingDefinition
内部
SettingsABC
的泛型类型和服务的get/set方法的泛型类型之间执行编译器类型检查。所以本质上,我可以做到:

Integer value = SettingsService.getSetting(SettingsABC.B.getDefinition());
SettingsService.setSetting(SettingsABC.A.getDefinition(), "A");
其中
B
的定义为
字符串类型

此外,我可以这样做:

Integer value = SettingsService.getSetting(SettingsABC.B.getDefinition());
SettingsService.setSetting(SettingsABC.A.getDefinition(), "A");
其中,
A
的定义是一个
整数


有没有办法使用泛型强制这两种不同的泛型类型匹配?

您可以将枚举转换为类:

public final class SettingsABC<T> {
    public static final SettingsABC<Integer> A = 
               new SettingsABC<>(new SettingDefinition<>("A", 123));
    public static final SettingsABC<String> B = 
               new SettingsABC<>(new SettingDefinition<>("B", "Hello"));
    public static final SettingsABC<Boolean> C = 
               new SettingsABC<>(new SettingDefinition<>("C", false));

    private final SettingDefinition<T> settingDefinition;

    // private constructor, so nobody else would instantiate it
    private SettingsABC(SettingDefinition<T> settingDefinition) {
            this.settingDefinition = settingDefinition;
    }

    public SettingDefinition<T> getDefinition() {
            return settingDefinition;
    }
}
虽然它不再是枚举,但它的使用方式基本相同。如果您需要在enum中通常可用的其他方法,您可以这样模拟它们:

String value = SettingsService.getSetting(SettingsABC.B.getDefinition());
SettingsService.setSetting(SettingsABC.A.getDefinition(), 123);
public String name() {
    return settingDefinition.getName();
}

@Override
public String toString() {
    return settingDefinition.getName();
}
// and so on

publicstaticvoidsetsetting(settingdefinitionsetting,t value)
会起作用吗?我想会,但不会。我在泛型方面没有那么丰富的经验,所以我无法解释为什么不能。您需要自己存储/传递
类。然后getter可以执行
返回clazz.cast(值)=您自己的类运行时存储。我看到原始类型!在描述泛型类时,切勿仅使用类型。即使是这样做的能力也是一种过时的向后兼容性混乱。您总是可以执行类似于
GenericType
的操作。对不起,伙计,我不明白这将如何替换原始类型。你能再详细一点吗?谢谢,这似乎更接近我的想法。我会进一步调查的。