实例化泛型类的子类

时间:2011-03-25 10:30:59

标签: java generics

我有简单的泛型类,如下所示:

public class Test<T extends Number> {

    public void doSomething() {
        Test t = new Test();
        t.getNumber();

    }

    public T getNumber() {
        T d = new Double("1.5"); // I get an compiler error here!
        return d;
    }
}

getNumber方法返回T(扩展Number),并在其实现中实例化Double。编译器在行上抛出错误:

    T d = new Double("1.5"); // I get an compiler error here!

错误是:

Incompatible types:
[ERROR] found   : java.lang.Double
[ERROR] required: T

由于T扩展了Number,我原本预计这会起作用。我错过了什么吗?

5 个答案:

答案 0 :(得分:3)

T extends Number,但这并不意味着它扩展了Double。 Double只是Number的已知子类之一。

答案 1 :(得分:1)

在左侧使用通用参数并在右侧使用特定实现是不对的。

答案 2 :(得分:1)

  1. 实例化测试时应该收到编译器警告。
  2. 想象一下,您实例化Test<Integer>。然后getNumber方法中的行变为:

    整数d = new Double(“1.5”);

  3. 显然,它应该抛出编译器错误。

    我认为您不应该使用泛型类型参数 - 将您的类替换为:

    public class Test {
        public Number getNumber() {
            Number d = Double.valueOf("1.5"); // No compiler error
            return d;
        }
    }
    

    另一个解决方案是表达你可以使用Double的任何超类作为类型参数的条件,即:

    public class Test<T super Double> {
        public T getNumber() {
            T d = Double.valueOf("1.5"); // No compiler error
            return d;
        }
    }
    

    一些一般提示:

    • 没有充分理由不要封装原始类型。
    • 不要使用new来实例化盒装基元类型,而是使用装箱类中的静态工厂方法。
    • 没有充分理由不要使用泛型类型。当你去定义泛型类型的麻烦时,不要在没有类型参数的情况下实例化它。

答案 3 :(得分:0)

T d = (T)new Double("1.5");

你必须输入强制转换为T.虽然它解决了你的问题但我对你正在做的事情感到怀疑。

答案 4 :(得分:0)

泛型类型定义class Test<T extends Number>表示选择创建Test类对象的人可以选择使用哪个类型参数。用户选择的不是您作为类实现者。

这意味着您无法确定它的类型,因此您的getNumber()方法只能安全地

  • 返回一个以某种方式作为T对象
  • 进入的对象
  • return null
  • 返回一个返回T的其他方法返回的对象。
    • 返回从Class<T>(或Class<? extends T>
    • 创建的对象
    • Collection<T>(或Collection<? extends T>
    • 返回一个对象
    • 类似的东西