Incompatible types: output variable E # 1 has incompatible upper bounds Enum <E # 2>

Why does this throw an error when building the project (but not when running unittests) ...

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);
}

      

... so far this works fine (note the difference - the last parameter - which is not used!):

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);
}

      

Mistake:

   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

      

What can I do to improve this?

Edit:

As additional information: this is how I call the method (using the second example, the first example is already shown in the error message):

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

      

And this is a simplified version of that enum:

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();
}

      

Now I understand that due to type inference, I seem to have to determine the type of the class, as shown in the second example. However, this is not my question. I am wondering 1: why the Gson library can do the same as me (as far as I can see from the code examples below) and 2: why this compilation fails in most cases when running unittests is not a problem.

Sample Gson code (method called in both examples):

@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;
}

      

Edit 2:

Apparently when I leave the "extends Enum" part the compiler no longer complains, so I don't need to pass this type as a parameter. (this looks more like the Gson example that caused it to compile for this code, but didn't compile for me in the 1st example). So now my first example:

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

      

Of course, I would still like to extend E to make sure the method can only be used to return enums.

Questions left:

  • How can I improve the code to solve this problem?
  • Why does this work without passing a specific type as a parameter, and why doesn't it work when expanding an Enum?
  • Why doesn't the compiler complain about the original 1st example when running unittests?
+3


source to share


1 answer


The type parameter in the first example has no way of knowing which specific type to replace. To solve this problem, there must be information in the argument list. In the second example, the argument Class<E>

provides the required information.



0


source







All Articles