反射问题 - 类型安全警告

时间:2010-05-26 15:50:04

标签: java

Class<? extends Algorithm> alg = AlgorithmAllFrom9AndLastFrom10Impl.class   
Constructor<Algorithm> c = alg.getConstructors()[0];

对于“alg.getConstructors()[0];”我在eclipse中收到警告

  

类型安全:类型的表达   构造函数需要未经检查的转换   符合构造函数

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:10)

Class<T>.getConstructors()的文档显示了问题:

  

Constructor<?>[] getConstructors():请注意,虽然此方法返回Constructor<T>个对象的数组(此类中的构造函数数组),但此方法的返回类型为Constructor<?>[],而不是可能会出现Constructor<T>[]。这个信息量较少的返回类型是必要的,因为从此方法返回后,可以修改数组以保存不同类的Constructor个对象,这将违反Constructor<T>[]的类型保证。

将此与Class<T>.getConstructor()重载进行比较:

  

Constructor<T> getConstructor(Class<?>... parameterTypes)

此重载实际上返回Constructor<T>

在您的情况下,由于您有Class<? extends Algorithm> algalg.getConstructor(parameterTypes)会返回Constructor<? extends Algorithm>(顺便说一句,不能安全地转换为Constructor<Algorithm>)。

只要有可能,即当你知道参数类型时,你应该总是更喜欢getConstructor(parameterTypes)getConstructors()[arbitraryIndex],因为对于后者你永远不能保证选择哪个构造函数。基于参数类型的选择是最具体的,并且如此处所示,对于泛型类型信息,它也更易于编译。

如果通过getConstructors()[0]你真的想要得到一个无效的构造函数,那么只需改为:

Constructor<? extends Algorithm> nullaryConstructor = alg.getConstructor();

摘要

所以你的问题有两个方面:

  • getConstructors()返回Constructor<?>[],表示所有类型信息都已丢失
  • 即使类型信息没有丢失(例如,使用getConstructor(parameterTypes)重载),您仍然只能获得Constructor<? extends Algorithm>(不是Constructor<Algorithm>)。
    • Class<T>.getConstructor(parameterTypes)返回Constructor<T>
    • 在您的情况下,类型参数T? extends Algorithm

另见

相关问题


讨论

遗憾的是,getConstructors()返回一个数组,因为正如dcoumentation中所解释的那样,因为数组协变,所以这会强制签名为Constructor<?>,从而丢失泛型类型信息。数组是可变的这一事实也意味着getConstructors()每次都必须创建一个新的数组实例!

    System.out.println(int.class.getConstructors().length); // prints "0"
    System.out.println(
        int.class.getConstructors() == int.class.getConstructors()
    ); // prints "false"!

理想情况下,getConstructors()应返回List<Constructor<T>>Class<T>应包含List;这不仅可以保留类型信息,而且getConstructors()也可以在每个{{1}}上返回相同的{{1}}对象。

有关此主题的更多讨论,请阅读 Effective Java 2nd Edition,第25项:首选列表到数组

答案 1 :(得分:0)

实际上没有施放到Constructor<Algorithm>我收到错误。

一个解决方案是执行Constructor<?> c = alg.getConstructors()[0];,因为这是getConstructors()返回的类型。

另一种方法是将@SuppressWarnings("unchecked")添加到该行,基本上告诉编译器“我确定这是Constructor<Algorithm>”,编译器无法告诉它。

答案 2 :(得分:0)

Constructor返回的getConstructors()数组具有无界通配符类型参数。您可以使用:

Constructor<?> c = alg.getConstructors()[0];

我认为getConstructors()不绑定其通配符的原因是因为这会导致通用数组。也许其中一种getConstructor()方法更适合您的需要。