Class<? extends Algorithm> alg = AlgorithmAllFrom9AndLastFrom10Impl.class
Constructor<Algorithm> c = alg.getConstructors()[0];
对于“alg.getConstructors()[0];”我在eclipse中收到警告
类型安全:类型的表达 构造函数需要未经检查的转换 符合构造函数
我该如何解决这个问题?
答案 0 :(得分: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]
你真的想要得到一个无效的构造函数,那么只需改为:
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()
方法更适合您的需要。