[英]Unchecked cast warnings in generic method on parameter that must be used in a List
在下面的代码中,类型参数D
可以是List<Byte>
或List<List<Byte>>
(它是Fields<?, ?, D>
接口中的第三个通用参数,但我可能还是忽略了它在那里-但它也存在于方法的返回类型中。 似乎找不到办法告诉编译器这一点-在标记为//*
的行中获取Unchecked cast
警告:
public static <D, K, T extends Enum<T> & Fields<?, ?, D>> List<EnumMap<T, D>>
getEntries(InputStream is, Class<T> fields) throws IOException {
final List<List<Byte>> entries = new ArrayList<List<Byte>>();
// populate "entries"
final boolean hasLists = hasLists(fields);
List<K> daBytes;
if (hasLists) {
daBytes = (List<K>) new ArrayList<EnumMap<T, List<List<Byte>>>>(); //*
} else {
daBytes = (List<K>) new ArrayList<EnumMap<T, List<Byte>>>(); //*
}
final int numOfEntries = entries.size();
for (int currentEntry = 0; currentEntry < numOfEntries; ++currentEntry) {
// add an element in daBytes for this currentEntry
if (hasLists) {
daBytes.add((K) new EnumMap<T, List<List<Byte>>>(fields)); //*
} else {
daBytes.add((K) new EnumMap<T, List<Byte>>(fields)); //*
}
for (T daField : fields.getEnumConstants()) {
List<Byte> field = new ArrayList<Byte>();
// populate "field"
D map = (D) daBytes.get(currentEntry);
if (hasLists) {
List<List<Byte>> fieldEntries = new ArrayList<List<Byte>>();
// populate "fieldEntries"
((EnumMap<T, List<List<Byte>>>) map).put(daField,
fieldEntries); //*
} else {
((EnumMap<T, List<Byte>>) map).put(daField, field); //*
}
}
}
return (List<EnumMap<T, D>>) daBytes; //*
}
如果hasLists
为false,则我需要D为List<Byte>
否则为List<List<Byte>>
。 daList
变量是List<EnumMap<T, D>>
。 现在,对我而言,定义:
List<EnumMap<T, D>> daBytes;
但是,一旦我这样做并更改:
if (hasLists) {
daBytes = (List<EnumMap<T, D>>) new ArrayList<EnumMap<T, List<List<Byte>>>>();
}
我得到一个错误:
无法从
ArrayList<EnumMap<T,List<List<Byte>>>>
为List<EnumMap<T,D>>
一直在绕行,使daBytes成为Object, List<?>
等,但始终使用导致警告的直接转换或通用转换。 必须有一种方法可以在没有强制转换的情况下进行干净地编译
我做了一些重构,提取了其他海报建议的“方法对象”。 这是所谓的“策略类”设计模式的一个实例。
无论您在哪里检查hasLists
我都会介绍一种抽象方法。 事实证明,您不再需要K
类型参数。
该代码在顶部产生一个未经检查的警告,在此我对hasLists
进行了选择以选择抽象类的实现。
public static <X, T extends Enum<T> & Fields<?, ?, List<X>>>
List<EnumMap<T, List<X>>> getEntries(InputStream is, Class<T> fields) throws IOException {
final List<List<Byte>> entries = new ArrayList<List<Byte>>();
// populate "entries"
FieldsStrategy<X, T> strategy = selectStrategy(fields);
return strategy.getEntries(entries);
}
private static <X, T extends Enum<T> & Fields<?, ?, List<X>>>
FieldsStrategy<X, T> selectStrategy(Class<T> fields) {
final boolean hasLists = hasLists(fields);
return hasLists
? (FieldsStrategy<X, T>) new ByteListFieldsStrategy(fields) //* this is the only unchecked warning
: (FieldsStrategy<X, T>) new ByteFieldsStrategy(fields); //* this is the only unchecked warning
}
private abstract static class FieldsStrategy<X, T extends Enum<T> & Fields<?, ?, List<X>>> {
private Class<T> fields;
public FieldsStrategy(Class<T> fields) {
this.fields = fields;
}
public List<EnumMap<T, List<X>>> getEntries(List<List<Byte>> entries) {
List<EnumMap<T, List<X>>> daBytes = new ArrayList<EnumMap<T, List<X>>>();
final int numOfEntries = entries.size();
for (int currentEntry = 0; currentEntry < numOfEntries; ++currentEntry) {
// add an element in daBytes for this currentEntry
daBytes.add(new EnumMap<T, List<X>>(fields));
for (T daField : fields.getEnumConstants()) {
EnumMap<T, List<X>> map = daBytes.get(currentEntry);
map.put(daField, getFieldData(daField));
}
}
return daBytes;
}
protected abstract List<X> getFieldData(T daField);
}
public static class ByteFieldsStrategy<T extends Enum<T> & Fields<?, ?, List<Byte>>>
extends FieldsStrategy<Byte, T> {
public ByteFieldsStrategy(Class<T> fields) {
super(fields);
}
protected List<Byte> getFieldData(T daField) {
ArrayList<Byte> field = new ArrayList<Byte>();
// populate "field"
return field;
}
}
public static class ByteListFieldsStrategy<T extends Enum<T> & Fields<?, ?, List<List<Byte>>>>
extends FieldsStrategy<List<Byte>, T> {
public ByteListFieldsStrategy(Class<T> fields) {
super(fields);
}
protected List<List<Byte>> getFieldData(T daField) {
List<List<Byte>> fieldEntries = new ArrayList<List<Byte>>();
// populate "fieldEntries"
return fieldEntries;
}
}
您可以通过移动hasLists()
逻辑和选择在Fields
接口上使用哪个策略类并在enum
类中实现它的开关来删除唯一剩余的未检查警告。
更新:这是selectStrategy
和Fields
的更新定义, 不会引起任何警告:
public static interface Fields<T extends Enum<T> & Fields<T, D, K>, D extends Data, K> {
// ....
GetEntries<K, T> selectStrategy();
}
private static <K, T extends Enum<T> & Fields<T, ?, K>>
GetEntries<K, T> selectStrategy(Class<T> fields) {
for (T field : fields.getEnumConstants()) {
return field.selectStrategy();
}
throw new IllegalArgumentException("Enum type has no instances: " + fields);
}
您需要在enum
类型中实现selectStrategy()
并返回适当的GetByteEntries
或GetByteListEntries
。
您现在可以删除hasLists()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.