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

Java 返回显式声明的超类的子类的泛型方法,java,generics,Java,Generics,目标 标题又长又混乱。。。我想要一种可以这样使用的方法: Double d = getAsNumber(Double.MAX_VALUE); Short s = getAsNumber(Short.MAX_VALUE); 该方法保证只接受java.lang.Number的子类 该方法将只返回传入的完全相同类的实例 传入的参数实际上是一个默认值,以防getAsNumber方法实际上没有值 到目前为止我拥有的 这实际上是可行的,但它很难看,我不明白为什么我需要显式地使用(t)进行强制转换。en

目标

标题又长又混乱。。。我想要一种可以这样使用的方法:

Double d = getAsNumber(Double.MAX_VALUE);
Short s = getAsNumber(Short.MAX_VALUE);
  • 该方法保证只接受java.lang.Number的子类
  • 该方法将只返回传入的完全相同类的实例
传入的参数实际上是一个默认值,以防getAsNumber方法实际上没有值

到目前为止我拥有的

这实际上是可行的,但它很难看,我不明白为什么我需要显式地使用(t)进行强制转换。enum感觉像是一个丑陋的解决方法,而且(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");
        }
    }
私有枚举数\u类{
双精度、浮点、整数、长、短
}
私有静态最终T getAsNumber(T defaultVal){
final String=“2”//通常从数据源获取
if(字符串==null){
返回defaultVal;
}
NUMBER_CLASS numberClass=NUMBER_CLASS.Double.valueOf(defaultVal.getClass().getSimpleName());
开关(numberClass){
双格:
return(T)Double.valueOf(string);//为什么需要显式强制转换!
案例长度:
返回(T)长。值(字符串);
违约:
抛出新的IllegalArgumentException(“必须给出java.lang.Number”);
}
}
一定有更好的办法吗?

**更新**


这里提出了多个问题。我实际上想问的主要问题是为什么我需要显式地使用(T)进行强制转换。在我看来,编译器拥有保证Double满足方法签名返回类型所需的所有信息。

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

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
。这就是需要强制转换的原因。

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

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
,因此没有强制转换,就可以使用
Double
参数等返回
Long
。这就是需要强制转换的原因。

没有更好的方法。在Java中泛化
Number
类型不可避免地会失败。(试着做你想做的转换课程也不可避免地会像你一样尴尬。)这是公平的,我承认我问了很多问题。。。不过,我有一个优先考虑的问题——为什么我需要明确的演员阵容?我想这是在学习。我将更新这个问题。Java中没有任何机制可以让编译器判断您已经“证明”
T
是任何特定类型。这不是Java的类型系统知道如何做的事情。那么我键入“”的值是什么呢?这不是说返回实例将是Number的实例吗?我们知道编译器可以测试Double是Number的子类-它会不断地进行这种类型的测试。你不能告诉编译器你已经知道了Number的子类是哪个。没有更好的方法了。在Java中泛化
Number
类型不可避免地会失败。(试着做你想做的转换课程也不可避免地会像你一样尴尬。)这是公平的,我承认我问了很多问题。。。不过,我有一个优先考虑的问题——为什么我需要明确的演员阵容?我想这是在学习。我将更新这个问题。Java中没有任何机制可以让编译器判断您已经“证明”
T
是任何特定类型。这不是Java的类型系统知道如何做的事情。那么我键入“”的值是什么呢?这不是说返回实例将是Number的实例吗?我们知道编译器可以测试Double是Number的子类-它经常进行这种类型的测试。你不能告诉编译器你已经知道了Number的子类是哪个。