简体   繁体   English

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

[英]Generic method that returns subclass of explicitly declared superclass

The Goal 目标

The title is long and confusing... I want a method which can be used like this: 标题很长而令人困惑......我想要一个可以像这样使用的方法:

Double d = getAsNumber(Double.MAX_VALUE);
Short s = getAsNumber(Short.MAX_VALUE);
  • The method is guaranteed to only accept a subclass of java.lang.Number 该方法保证只接受java.lang.Number的子类
  • The method will only return an instance of the exact same class that was passed in 该方法仅返回传入的完全相同类的实例

The parameter being passed in is actually a default value in case the getAsNumber method doesn't actually have a value. 传入的参数实际上是一个默认值,以防getAsNumber方法实际上没有值。

What I have so far 到目前为止我有什么

This is actually working but it's ugly and I don't understand why the heck I need to explicitly cast with (T). 这实际上是有效的,但它很难看,我不明白为什么我需要明确地使用(T)。 The enum feels like an ugly workaround, and (T) shouldn't be necessary, the compiler KNOWS that Double or Long is a subclass of Number... 枚举感觉就像一个丑陋的解决方法,并且(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");
        }
    }

There must be a better way? 一定会有更好的办法?

** UPDATE ** ** 更新 **

Multiple questions are posed here. 这里提出了多个问题。 The main question I'm actually after is why I needed to explicitly cast with (T). 我实际上追求的主要问题是为什么我需要使用(T)显式转换。 It seems to me the compiler has all of the information it needs in order to guarantee that Double will meet the method signature's return type. 在我看来,编译器具有它需要的所有信息,以保证Double将满足方法签名的返回类型。

The compiler is unable to find what is your function internal reasoning. 编译器无法找到您的函数内部推理。 Imagine the code: 想象一下代码:

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

The return value isn't formally connected to the type T so without the cast it's possible to return Long with Double argument, etc. That's why the cast is needed. 返回值并未正式连接到类型T因此如果没有强制转换,则可以使用Double参数返回Long等。这就是需要强制转换的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM