返回显式声明的超类的子类的泛型方法

时间:2017-03-21 23:30:56

标签: java generics

目标

标题很长且令人困惑......我想要一种可以像这样使用的方法:

Double d = getAsNumber(Double.MAX_VALUE);
Short s = getAsNumber(Short.MAX_VALUE);
  • 保证该方法只接受java.lang.Number
  • 的子类
  • 该方法仅返回与
  • 中传递的完全相同的类的实例

传入的参数实际上是一个默认值,以防getAsNumber方法实际上没有值。

到目前为止我有什么

这实际上有效,但它很难看,我不明白为什么我需要明确地使用(T)。枚举感觉就像一个丑陋的解决方法,并且(T)不应该是必要的,编译器知道Double或Long是Number的子类...

 private enum NUMBER_CLASS {
        Double, Float, Integer, Long, Short
    }

    private static final <T extends Number> T  getAsNumber( T defaultVal ) {
        final String string = "2";//would normally get from data source
        if (string==null) {
            return defaultVal;
        }

        NUMBER_CLASS numberClass = NUMBER_CLASS.Double.valueOf(defaultVal.getClass().getSimpleName());
        switch (numberClass) {
            case Double:
                return (T) Double.valueOf(string); // WHY is explicit cast necessary!
            case Long:
                return (T) Long.valueOf(string);
            default:
                throw new IllegalArgumentException("Must give a java.lang.Number");
        }
    }

必须有更好的方法吗?

** 更新 **

这里提出了多个问题。我实际上追求的主要问题是为什么我需要使用(T)显式转换。在我看来,编译器具有它需要的所有信息,以保证Double符合方法签名的返回类型。

1 个答案:

答案 0 :(得分:0)

编译器无法找到您的函数内部推理。想象一下代码:

switch (numberClass) {
    case Double:
        return Long.valueOf(string); // If there is no cast it will broke type system
    case Long:
        return Double.valueOf(string); // The same
    default:
        throw new IllegalArgumentException("Must give a java.lang.Number");
}

返回值未正式连接到类型T,因此如果没有强制转换,则可以使用Long参数等返回Double。这就是需要强制转换的原因。< / p>