java - 不兼容的类型 : inference variable E#1 has incompatible upper bounds Enum<E#2>

标签 java generics enums

为什么在我构建项目时会抛出错误(但在运行单元测试时不会)...

protected <E extends Enum<E>> E getEnum(JSONObject jsonObject, String propertyName, Type type)
{
    String jsonString = jsonObject.optString(propertyName, null);
    return new GsonBuilder().create().fromJson(jsonString, type);
}

...虽然这完全有效(注意区别 - 最后一个参数 - 未使用!):

protected <E extends Enum<E>> E getEnum(JSONObject jsonObject, String propertyName, Type type, Class<E> clazz)
{
    String jsonString = jsonObject.optString(propertyName, null);
    return new GsonBuilder().create().fromJson(jsonString, type);
}

错误:

   warning: [options] bootstrap class path not set in conjunction with -source 1.7 C:\Projects\bla\bla\bla.java:32: error: incompatible types: inference variable E#1 has incompatible upper bounds Enum<E#2>,Termination
    Termination termination = getEnum(jsonObject, "termination", Termination.TYPE);                                                         
    where E#1,E#2 are type-variables:
      E#1 extends Enum<E#1> declared in method <E#1>getEnum(JSONObject,String,Type)
      E#2 extends Termination

我应该做什么来改善这个问题?

编辑:

作为附加信息:这就是我调用该方法的方式(使用第二个示例,第一个示例已显示在错误消息中):

Termination termination = getEnum(jsonObject, "termination", Termination.TYPE, Termination.class).

这是该枚举的简化版本:

public enum Termination
{
    @SerializedName("endDate")END_DATE, 
    @SerializedName("recurrenceCount")COUNT,
    @SerializedName("forever")FOREVER;

    public static final java.lang.reflect.Type TYPE = new TypeToken<Termination>(){}.getType();
}

现在我明白 - 由于类型推断 - 我显然需要定义类类型,如第二个示例所示。然而,这不是我的问题。我想知道 1:为什么 Gson 库能够做与我完全相同的事情(据我从下面的代码示例中可以看到),以及 2:为什么在运行单元测试时在大多数情况下不能编译没问题。

Gson示例代码(两个示例中调用的方法):

@SuppressWarnings("unchecked")
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
  if (json == null) {
    return null;
  }
  StringReader reader = new StringReader(json);
  T target = (T) fromJson(reader, typeOfT);
  return target;
}

编辑2:

显然,当我省略“扩展枚举”部分时,编译器不再提示,因此我不需要将类型作为参数传递。 (这看起来更像 Gson 示例,这就是为什么它为该代码编译但在第一个示例中没有为我编译的原因)。所以我的第一个例子现在变成:

protected <E> E getEnum(JSONObject jsonObject, String propertyName, Type type)
{
    String jsonString = jsonObject.optString(propertyName, null);
    return new GsonBuilder().create().fromJson(jsonString, type);
}

当然,我仍然想扩展 E 以确保该方法只能用于返回枚举。

剩余问题:

  1. 如何改进代码来解决这个问题?
  2. 为什么在不传递具体类型作为参数的情况下它可以工作,为什么在扩展 Enum 时它不起作用?
  3. 为什么编译器在运行单元测试时不会提示原始的第一个示例?

最佳答案

第一个示例中的类型参数无法知道要替换什么具体类型。参数列表中必须有信息来解决该问题。在第二个示例中 Class<E>论证提供了必要的信息。

关于java - 不兼容的类型 : inference variable E#1 has incompatible upper bounds Enum<E#2>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44166466/

相关文章:

Java:如何使用遵循(通用)可扩展枚举类型模式的字段创建不可变值对象

java - 使用单表继承对子类进行 JPA 查询

java - 在共享路径中查找可用的java版本的jdk

c# - 如何对泛型类进行排序?

将 argv[] 与允许元素列表进行比较

c++ - 关于强类型枚举前向声明

java - Files.exists(path) 为假,但 file.exists() 为真

java - 如何使用反射在 JDK8 中将 Lambda 表达式作为方法参数传递

Java 通用类型变量

java - 扩展实现某些包含泛型的类的 ArrayList 不起作用?