嗨,是否可以投射一个列表?
我有一个抽象类,它有一个方法,它采用某种List<>,在for循环中迭代它,获取该列表中的每个对象,并调用子类实现的insertItem抽象方法基本上拉出项目中的正确数据,然后最终将它们插入数据库表。
这是超类方法:
protected void insertAllItemsToDb(List<Object> items, String table) {
// open db and table
database().beginTransaction();
// clear all data from table
clearTable(table);
// call a insert statement to insert each column from an item
for (Object object : items) {
insertItem(object, table);
}
// close db
database().endTransaction();
database().close();
}
在子类中,这是一个覆盖方法:我可以在这里强制转换对象。
@Override
protected void insertItem(Object object, String table) {
CalendarEventItem item = (CalendarEventItem) object;
eventItemValue = new ContentValues();
eventItemValue.put(LABEL_EVENTS_TITLE, item.getEventTitle());
eventItemValue.put(LABEL_EVENTS_LOCATION, item.getEventLocation());
eventItemValue.put(LABEL_EVENTS_DATE, item.getEventStartTime()
.getDate());
eventItemValue.put(LABEL_EVENTS_TIME, item.getEventStartTime()
.getTime());
eventItemValue.put(LABEL_EVENTS_TIMEZONE, item.getEventStartTime()
.getTimeZone());
database.insert(TABLE_NAME_EVENTS, null, eventItemValue);
}
然后我使用以下方法从超类中调用该方法:
events = (List<CalendarEventItem>) items;
insertAllItemsToDb(events, TABLE_NAME_EVENTS);
但我收到一个编译错误,说你不能施展它。关于如何实现这一点的任何想法,而不必复制您在insertAllItemsToDb()中看到的相同步骤和代码
答案 0 :(得分:6)
将通用参数添加到抽象类:
public abstract class BaseClass<T>{
protected abstract void insertItem(T object, String table);
protected void insertAllItemsToDb(List<T> items, String table) {
//...
for (T object : items) {
insertItem(object, table);
}
//...
}
}
现在您不需要任何转换,子类只需使用正确的类型:
public class FooBar extends BaseClass<Phleem>{
protected void insertItem(Phleem object, String table){
// ...
}
}
答案 1 :(得分:5)
List<Object>
不 a List<CalendarEventItem>
,因此编译器是正确的,它们不可转换。快速的原因,这是一个例子:
final List<Object> listOne = new ArrayList<Object>();
listOne.add("Hello World");
final List<CalendarEventItem> listTwo = new ArrayList<CalendarEventItem>();
listTwo.addAll(listOne); // Correctly disallowed by compiler
// This is what you're trying to do
List<CalendarEventItem> sneakyList = (List<CalendarEventItem>)listOne;
listTwo.addAll(sneakyList);
因此,不允许在两种不兼容类型之间进行转换,因为它会破坏类型安全保证。
您几乎肯定希望声明insertAllItemsToDb
方法采用List<?>
而不是List<Object>
,因为您不关心元素类型是什么,只要它是一个Object的子类(这很简单)。
这可以防止您在不可转换的类型之间进行投射,并且通常可以更好地使用。
有关更多信息,请查看Angelika Langer出色的Java Generics FAQ的“通配符”部分。事实上,如果你还没有,你应该看看整个事情。要带走的一般原则是,在大多数情况下,您应该在用于方法参数的集合上使用通配符 - 唯一的情况是,如果您同时读取和写入集合(实际上是非常罕见的。)
答案 2 :(得分:0)
您也可以将方法参数声明为常规列表,然后将其强制转换为方法中所需的任何通用列表,即您的方法为protected void insertAllItemsToDb(List items, String table)
,并将第一行转换为:{{ 1}} ...当然实现了在做这样的事情时你应该采取的任何类型的检查/错误捕获。