反射问题 - 类型安全警告

jax*_*jax 2 java

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

对于"alg.getConstructors()[0];" 我在日食中得到警告

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

我该如何解决?

pol*_*nts 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> alg,alg.getConstructor(parameterTypes)返回一个Constructor<? extends Algorithm>(顺便说一句,不能安全地转换Constructor<Algorithm>).

只要有可能,即当你知道参数类型,你应该总是喜欢getConstructor(parameterTypes)getConstructors()[arbitraryIndex],因为与构造函数将被选中你从来没有完全保证后者.基于参数类型的选择是最具体的,并且如此处所示,对于通用类型信息而言也更加编译器友好.

如果getConstructors()[0]您真的想要获得nullary构造函数,那么只需执行此操作:

Constructor<? extends Algorithm> nullaryConstructor = alg.getConstructor();
Run Code Online (Sandbox Code Playgroud)

摘要

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

  • getConstructors()返回a Constructor<?>[],表示所有类型信息都丢失了
  • 即使类型信息没有丢失(例如通过使用getConstructor(parameterTypes)过载),你仍然只能得到Constructor<? extends Algorithm>最好的(不是a 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"!
Run Code Online (Sandbox Code Playgroud)

理想情况下getConstructors()应该返回一个List<Constructor<T>>应该被包裹的Collections.unmodifiableList; 这不仅可以保留类型信息,还Class<T>可以List在每个信息上返回相同的对象getConstructors().

有关此主题的更多讨论,请阅读Effective Java 2nd Edition,Item 25:Prefer list to arrays.