Search code examples
javaeclipsegenericscompilationjavac

compiling generics with javac compiler


I am getting the following error when using javac (related to java generics)

:inconvertible types
[ERROR] required: (...)
[ERROR] found:    (...)

The code is compiling fine in eclipse (since it is not using javac ).

Im getting errors on the following code:

public <T extends Comparable<T>> TRange<T> valueToRange(T val, List<T> rangeValues) {
    List<T> vals = rangeValues;
    if (vals == null) {
        vals = (List<T>) (this.values != null ? this.values : this.defaultValues);
    }
    return valueToRange(val, vals, this.range);
}

where values and defaultValues are of type List of Serializable

and

public static <T extends Enum<T> & Unit> Class<T> getEnumClass(String unitValueClassName) {
    unitValueClassName = normalizeEnumClassName(unitValueClassName);

    if (unitValueClassName.equals(DENSITY_CLS)) {
        return (Class<T>) DensityUnit.class;
    }
    if (unitValueClassName.equals(LENGTH_CLS)) {
        return (Class<T>) LengthUnit.class;
    }
    if (unitValueClassName.equals(LENGTH_OPTIONAL_CLS)) {
        return (Class<T>) LengthUnit.class;
    }
    if (unitValueClassName.equals(VOLUME_CLS)) {
        return (Class<T>) VolumeUnit.class;
    }
    if (unitValueClassName.equals(WEIGHT_CLS)) {
        return (Class<T>) WeightUnit.class;
    }
    if (unitValueClassName.equals(TIME_CLS)) {
        return (Class<T>) TimeUnit.class;
    }
    throw new IllegalArgumentException("Please add the enum class to UnitValueView.getEnumClass(String) : " + unitValueClassName);
}

can we re-write them in another way that keeps the same functionality but passes javac compiler ?


Solution

  • The first code snippet is actually dangerous: you are trying to convert List<Serializable> to List<T> where T is Comparable<T>. You may end up with non-comparable items inside the list of Comparable which may produce sudden ClassCastException in runtime. Without knowing the implementation of three-argument valueToRange I cannot say how to fix this properly. But if you still feel that this is ok and just want this code to be compilable, you may add one more cast:

    public <T extends Comparable<T>> TRange<T> valueToRange(T val, List<T> rangeValues) {
        List<T> vals = rangeValues;
        if (vals == null) {
            vals = (List<T>) (List<?>) (this.values != null ? this.values : this.defaultValues);
        }
        return valueToRange(val, vals, this.range);
    }
    

    With the second example you may do something similar:

    public static <T extends Enum<T> & Unit> Class<T> getEnumClass(String unitValueClassName) {
        unitValueClassName = normalizeEnumClassName(unitValueClassName);
    
        Class<?> clazz;
        if (unitValueClassName.equals(DENSITY_CLS)) {
            clazz = DensityUnit.class;
        } else if (unitValueClassName.equals(LENGTH_CLS)) {
            clazz = LengthUnit.class;
        } else if (unitValueClassName.equals(LENGTH_OPTIONAL_CLS)) {
            clazz = LengthUnit.class;
        } else if (unitValueClassName.equals(VOLUME_CLS)) {
            clazz = VolumeUnit.class;
        } else if (unitValueClassName.equals(WEIGHT_CLS)) {
            clazz = WeightUnit.class;
        } else if (unitValueClassName.equals(TIME_CLS)) {
            clazz = TimeUnit.class;
        } else {
            throw new IllegalArgumentException("Please add the enum class to UnitValueView.getEnumClass(String) : " + unitValueClassName);
        }
        return (Class<T>) clazz;
    }