我有以下课程:
abstract class DTO{ }
class SubscriptionDTO extends DTO { }
以及以下通用方法:
protected void fillList(ResultSet rs, ArrayList<? extends DTO> l)
throws BusinessLayerException {
SubscriptionDTO bs;
try {
while (rs.next()){
//initialize bs object...
l.add(bs); //compiler error here
}
} catch (SQLException e) {
e.printStackTrace();
}
}
我似乎无法理解为什么你不能创建一个填充DTO子类型的通用方法。我做错了什么还是这个设计?如果是这样,有没有解决方法?提前谢谢。
答案 0 :(得分:7)
您应该使用<? super DTO>
(或<? super SubscriptionDTO>
,Tom Hawtin - tackline指出)作为ArrayList
的通用参数。
Effective Java第28项(sample chapter [pdf]第28页):
这是一个助记符,可帮助您记住要使用的通配符类型:
PECS代表生产者延伸,消费者超级。
换句话说,如果参数化类型代表
T
生产者,请使用<? extends T>
; 如果它代表T
个消费者,请使用<? super T>
。
在这种情况下,l
是使用者(您将对象传递给它),因此<? super T>
类型是合适的。
答案 1 :(得分:2)
想象一下Foo extends Bar
和Zoo extends Bar
List<Foo> fooList = new ArrayList<Foo>();
fooList.addAll(aBunchOfFoos());
aMethodForBarLists(fooList);
然后我们有了方法本身:
void aMethodForBarLists (List<? extends Bar> barList) {
barList.add(new Zoo());
}
这里发生的是,即使Zoo确实扩展了Bar,你也试图在List<Foo>
中添加一个动物园,这是为Foos明确制作的。
这个是Java规范不允许在<? extends Something>
集合中添加内容的原因 - 它不能确定,虽然语法似乎正确,实际对象允许将内容添加到Collection中。
答案 2 :(得分:2)
这应该有效,而且更直接:
protected void fillList( ResultSet rs, List<DTO> l ) throws BusinessLayerException
{
SubscriptionDTO bs;
try
{
while ( rs.next() )
{
//initialize bs object...
l.add( bs );
}
}
catch ( SQLException e )
{
e.printStackTrace();
}
}