【发布时间】:2014-01-05 13:50:21
【问题描述】:
我们正在尝试在包含版本化的 bean 集(用于 XML Web 服务)的库中提取接口。模型本身仅使用相同版本的其他模型。
大多数情况下只有 getter 和 setter,并且由于版本非常相似,因此该过程大部分时间都运行良好。不过,对于 List 类型,有一点小问题。
举个例子:
public class Attribute implements IAttribute
这是在别处使用的:
public class Product implements IProduct {
List<Attribute> products = new ArrayList<Attribute>();
}
接口IProduct有这个getter和setter:
public interface IProduct {
public abstract List<? extends IAttribute> getAttributes();
public abstract void setAttributes(List<? extends IAttribute> attributes);
}
Product 类有这个 getter 和 setter:
public List<Attribute> getAttributes() {
return attributes;
}
public void setAttributes(List<? extends IAttribute> attributes) {
this.attributes = attributes;
}
当然,setter 上有一个错误:Product 中的字段属性是一个属性列表,并且比扩展 IAttribute 的通配符列表更窄。不过感觉就像是第 22 条陷阱。如果我们扩大领域本身的声明,我们就会失去特异性的好处。然后还有实现添加方法(addAttribute(Attribute attribute))的问题。
一个丑陋的解决方案是遍历扩展 IAttribute 的通配符列表,进行类型检查并仅当内部对象的实际类型是正确版本的 Attribute 时才添加。
public void setAttributes(List<? extends IAttribute> attributes) {
this.attributes = new ArrayList<Attribute>();
for (Attribute attribute : attributes) {
if (!(attribute instanceof Attribute)) {
throw new IllegalArgumentException();
} else {
this.attributes.add((Attribute)attribute);
}
}
}
有没有更好、更健壮、更优雅的方法来做到这一点?
【问题讨论】:
-
如果您确定类型正确,只需强制转换并忽略警告 -
this.attributes = (List<Attribute>) attributes。如果您不确定类型是否正确,那么您必须像所做的那样检查每个演员表。随着泛型被删除,错误的转换可能会导致代码中某处出现ClassCastException。