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?
source to share