使用 javac 编译器编译泛型

compiling generics with javac compiler

我在使用 javac 时遇到以下错误(与 java 泛型有关)

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

代码在 eclipse 中编译正常(因为它没有使用 javac )。

我在以下代码中遇到错误:

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

其中值和 defaultValues 属于 Serializable

List 类型

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

我们可以用另一种保持相同功能但通过 javac 编译器的方式重写它们吗?

第一个代码片段实际上是危险的:您试图将 List<Serializable> 转换为 List<T>,其中 TComparable<T>。您最终可能会在 Comparable 列表中得到 non-comparable 项,这可能会在运行时突然产生 ClassCastException。不知道 three-argument valueToRange 的实现,我不能说如何正确解决这个问题。但是如果你还是觉得这样还可以,只是想让这段代码可以编译,可以再加一个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);
}

对于第二个例子,你可以做类似的事情:

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