【问题标题】:compiling generics with javac compiler使用 javac 编译器编译泛型
【发布时间】:2016-01-10 17:14:26
【问题描述】:

使用 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 的类型为ListSerializable

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 编译器?

【问题讨论】:

  • 您为什么选择不发布您的问题所涉及的错误消息?
  • 首先,(Class&lt;T&gt;) 因为类型擦除而毫无结果。应该是(Class&lt;?&gt;),这是您可以安全获得的更精确的值。如果你真的需要它是通用的,你应该打电话给Class.cast
  • 在第一个示例中,您尝试将 List&lt;Serializable&gt; 转换为 List&lt;T&gt; - 为什么?

标签: java eclipse generics compilation javac


【解决方案1】:

第一个代码 sn-p 实际上很危险:您正在尝试将List&lt;Serializable&gt; 转换为List&lt;T&gt;,其中TComparable&lt;T&gt;。您最终可能会在Comparable 列表中找到不可比较的项目,这可能会在运行时突然产生ClassCastException。在不知道三参数 valueToRange 的实现的情况下,我无法说出如何正确解决此问题。但是如果你仍然觉得这样没问题,只是希望这段代码是可编译的,你可以再加一个演员表:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-20
    • 2011-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多