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>.
在你的情况下,因为你有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.