[英]Type Safety warning when casting to generic class in Java
I have a class 我有一堂课
class Property<T> {
value T;
public void setValue(T value) {
this.value = value;
}
}
Now I have a list List<Property<?>> properties
with various properties of various Types. 现在,我有了一个列表
List<Property<?>> properties
其中包含各种类型的各种属性。 I loop through this list and want to set the value of every Property. 我遍历此列表,并希望设置每个属性的值。 Therefore I need to cast the generic Property to the correct type like: eg for Integer:
因此,我需要将通用属性转换为正确的类型,例如:对于Integer:
if (property.getType().equals("Integer")) {
Property<Integer> propInt = (Property<Integer>) property;
propInt.setValue((Integer) values[i++]);
}
where values[]
is an Object array which holds the values that I want to set. 其中
values[]
是一个对象数组,其中包含我要设置的值。
Everything works fine, but Java complains about Type Safety "Unchecked cast from Property<?>
to Property<Integer>
". 一切正常,但是Java抱怨类型安全“未经检查从
Property<?>
到Property<Integer>
”。 A check like 像这样的支票
if (property instanceof Property<Integer>){...}
is not possible though. 虽然不可能。 How can I change my code to get rid of this warning, or do you know a better practice for my case?
我该如何更改代码以消除此警告,或者您知道我的案例的更好做法?
The compiler complains because property
is of type Property<?>
which could or could not be of type Property<Integer>
in general. 编译器抱怨是因为
property
的类型为Property<?>
,通常它可能是也不可能是Property<Integer>
类型。 This is an inherent limitation of the current java language due to type erasure. 由于类型擦除,这是当前Java语言的固有限制。
In this particular case you are making sure that property
is of class Property<Integer>
by use of the getType
method so it is safe to ignore the warning. 在这种特殊情况下,您可以通过使用
getType
方法来确保该property
属于Property<Integer>
类,因此可以安全地忽略该警告。
if (property.getType().equals("Integer")) {
// we have made sure property is of class Property<Integer> so the cast is type safe
@SuppressWarnings("unchecked")
Property<Integer> propInt = (Property<Integer>) property;
propInt.setValue((Integer) values[i++]);
}
It is important to document it with a comment otherwise a peer reviewing your code might not notice that indeed the cast is type safe and could confuse the warning supression as a malpractice. 重要的是要用注释记录下来,否则查看您的代码的同行可能不会注意到确实类型转换是安全的,并且可能将警告抑制作为不当行为加以混淆。
The warning indicates, that at source level, the list may contain objects of any type () and you cast those to Integer, which would lead to a ClassCastException at runtime, in cases where the list contains a non-Integer object. 警告表明,在源级别,列表可能包含任何类型()的对象,并且将它们强制转换为Integer,如果列表包含非Integer对象,则在运行时会导致ClassCastException。 So the warning indicates a potential problem at runtime.
因此,警告表明在运行时存在潜在问题。
You could get rid of the warning by either 您可以通过以下两种方法摆脱警告
List<Integer>
List<Integer>
@SuppressWarnings("unchecked")
on the method or the list declaration. @SuppressWarnings("unchecked")
警告。 If you can not guarantee, that the objects contained in the list are no Integer, then you should have the instanceof
before the cast and the SuppressWarning. 如果不能保证列表中包含的对象不是Integer,则在转换和SuppressWarning之前应该具有
instanceof
。 If you can guarantee it, then you should declare the list as list of Integers. 如果可以保证,则应将该列表声明为Integers列表。
You can use annotation SuppressWarnings
to ignore this warning: 您可以使用
annotation SuppressWarnings
忽略此警告:
@SuppressWarnings("unchecked") Property<Integer> propInt = (Property<Integer>) property;
but it's a risk to do this. 但是这样做是有风险的。
this warning is caused by type erasure , because when compile, generic type will be erased. 此警告是由于类型擦除引起的,因为在编译时, 泛型将被擦除。
As you know generics in java suffer a bit from type erasure, all becomes Object at run-time. 如您所知,java中的泛型会遭受类型擦除,所有这些在运行时都变为Object。
As you test on strings like "Integer", it would seem adding a Class<T>
could even be convenient. 当您对“ Integer”之
Class<T>
字符串进行测试时,添加Class<T>
似乎更为方便。
class Property<T> {
final Class<T> type;
value T;
public Property(Class<T> type) {
this.type = type;
}
public void setAnyValue(Object value) {
this.value = type.cast(value);
}
}
Property<?> property = ...
//if (property.getType() == Integer.class) {
// Property<Integer> propInt = (Property<Integer>) property;
// propInt.setAnyValue((Integer) values[i++]);
//}
property.setAnyValue(values[i++]);
The usage of Object is due to the polymorph usage of Property instead of the more normal typing: your code mixes up differently typed properties and parallel values. Object的使用归因于Property的多态使用,而不是更普通的键入:您的代码混合了不同类型的属性和并行值。
import static org.springframework.data.util.CastUtils.cast;
Map<String,Object> messageMap = cast(exchange.getMessage().getBody());
List<String> refIds = cast(messageMap.get("refIds"));
I wouldn't suggest using this unless the spring framework is already part of your application. 除非spring框架已成为您应用程序的一部分,否则我不建议您使用此功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.