java - 泛型工厂的泛型和类型推断

标签 java generics type-inference

对于这个问题中任何糟糕的英语语言,提前表示歉意。

我想创建一种工厂,它只能创建在由具体工厂实例类实现的列表中定义的类的实例。首先,我定义了这个接口(interface):

public interface ValuesSystem {

    public interface AllowedValue<T extends Class<? extends SystemValue>>{};

    AllowedValue<Class<? extends SystemValue>> getAllowedValue(Enum<?> id);

    Map<? extends Enum<?>, AllowedValue<Class<? extends SystemValue>>> getAllowedValues();

    <T extends SystemValue> T create(AllowedValue<Class<T>> allowedClass, ValueData data) throws InvalidValueException;
}

AllowedValue 接口(interface)只是一个“标记包装器”接口(interface),它使用泛型来定义“允许”由我的工厂创建的类实例。

getAllowedValue 是一种方法,用于使用实现此接口(interface)的具体类的内部枚举从我允许的类“列表”中获取包装的允许类实例(具体类的示例将出现)。

create 方法旨在最终创建 allowedClass 参数中给出的我允许的 Class 实例的实例。

下面是一个实现这个接口(interface)的具体类的例子:

public class BasicValueSystem implements ValuesSystem {

    public BasicValueSystem() {
        super();
        allowedValues = (Map<VALUES_ID, AllowedValue<Class<? extends SystemValue>>>) getAllowedValues();
    }

    public static enum VALUES_ID {
        MODIFIER
    }

    private static Map<VALUES_ID, AllowedValue<Class<? extends SystemValue>>> allowedValues;

    private class BasicAllowedValue<T extends Class<? extends SystemValue>>
            implements AllowedValue<Class<? extends SystemValue>> {

    }

    @Override
    public <T extends SystemValue> T create(
            AllowedValue<Class<T>> allowedClass, ValueData data)
                throws InvalidValueException {
        if (!(allowedClass instanceof BasicAllowedValue)) {
            throw new InvalidValueException();
        }
        return null;
    }

    @Override
    public AllowedValue<Class<? extends SystemValue>> getAllowedValue(Enum<?> id) {
        return allowedValues.get(id);
    }

    @Override
    public Map<? extends Enum<?>, AllowedValue<Class<? extends SystemValue>>> getAllowedValues() {
        Map<VALUES_ID, AllowedValue<Class<? extends SystemValue>>> allowed = new EnumMap<VALUES_ID, AllowedValue<Class<? extends SystemValue>>>(VALUES_ID.class);
        allowed.put(VALUES_ID.MODIFIER, new BasicAllowedValue<Class<ModifierValue>>());
        return allowed;
    }
}

目前create方法返回null,但问题出在其他地方,这不是我的问题

当我尝试使用以下代码创建我的“允许”值实例之一的实例时出现问题:

BasicValueSystem bvs = new BasicValueSystem();
AllowedValue<Class<? extends SystemValue>> allowed = bvs
    .getAllowedValue(BasicValueSystem.VALUES_ID.MODIFIER);
bvs.create(allowed, new ModifierValueData());

编译器告诉我:

The method create(ValuesSystem.AllowedValue<Class<T>>, ValueData) in the type BasicValueSystem is not applicable for the arguments (ValuesSystem.AllowedValue<Class<? extends SystemValue>>, ModifierValueData)

我想我错过了一些关于一般泛型所做的类型推断的事情。

任何人都可以向我解释创建方法签名在这种情况下不适用以及如何解决它吗?

提前感谢您抽出宝贵时间。

最佳答案

请注意 public interface AllowedValue<T extends Class<? extends SystemValue>>没有多大意义。 T 的唯一有效类型将是 Class<? extends SystemValue>作为类(class)Class是最终的,不能有子类。所以你可以用interface AllowedValue<Class<? extends SystemValue>>代替它语义没有任何变化,但你真正的意思(恕我直言)是 interface AllowedValue<T extends SystemValue> .不要乱用Class在类型签名中。该接口(interface)仍然可能有引用 Class<T> 的方法那么。

public interface ValuesSystem {

  public interface AllowedValue<T extends SystemValue>{};

  AllowedValue<? extends SystemValue> getAllowedValue(Enum<?> id);

  public <T extends SystemValue> T create
                     (AllowedValue<T> allowedClass, ValueData data);
}

相应地调整实现,BasicAllowedValue成为

private class BasicAllowedValue<T extends SystemValue> implements AllowedValue<T>

然后您使用代码的问题就消失了。

BasicValueSystem bvs = new BasicValueSystem();
AllowedValue<? extends SystemValue> allowed = bvs
    .getAllowedValue(BasicValueSystem.VALUES_ID.MODIFIER);
bvs.create(allowed, new ModifierValueData());

将编译。


请注意,如果 AllowedValue应仅保留没有方法的标记接口(interface),这是不必要的,Class<T>已经完成了这个角色。这样做时它也会起作用:

public interface ValuesSystem {
  Class<? extends SystemValue> getAllowedValue(Enum<?> id);
  public <T extends SystemValue> T create(Class<T> allowedClass, ValueData data);
}

BasicValueSystem bvs = new BasicValueSystem();
Class<? extends SystemValue> allowed = bvs
    .getAllowedValue(BasicValueSystem.VALUES_ID.MODIFIER);
bvs.create(allowed, new ModifierValueData());

关于java - 泛型工厂的泛型和类型推断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20100154/

相关文章:

java - 设置按钮背景颜色

java - Singleton Bean UDP 监听器

ios - 泛型类类型不符合 Any

OCaml的let多态实现

Haskell 泛型类型参数解析器工具或方法

java - 如何在底部设置textview

java - 是否支持 log4j.properties 文件包含?

c# - 具有类型约束或基类参数的通用方法

java - 重写通用 equals 方法

c# - C# 类型推断有多好?