投射名单<>在java?

时间:2010-10-27 14:19:24

标签: java

嗨,是否可以投射一个列表?

我有一个抽象类,它有一个方法,它采用某种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()中看到的相同步骤和代码

3 个答案:

答案 0 :(得分:6)

使用Type参数

将通用参数添加到抽象类:

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}} ...当然实现了在做这样的事情时你应该采取的任何类型的检查/错误捕获。