在java中强制列出<>?

jon*_*ney 2 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();
    }
Run Code Online (Sandbox Code Playgroud)

在子类中,这是一个覆盖方法:我能够在这里强制转换对象.

  @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);

    }
Run Code Online (Sandbox Code Playgroud)

然后我使用以下方法从超类中调用该方法:

events =  (List<CalendarEventItem>) items;
        insertAllItemsToDb(events, TABLE_NAME_EVENTS);
Run Code Online (Sandbox Code Playgroud)

但我收到一个编译错误,说你不能施展它.关于如何实现这一点的任何想法,而不必复制您在insertAllItemsToDb()中看到的相同步骤和代码

Sea*_*oyd 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);
        }
        //...
    }

}
Run Code Online (Sandbox Code Playgroud)

现在你不需要任何转换,子类只需要使用正确的类型:

public class FooBar extends BaseClass<Phleem>{
    protected void insertItem(Phleem object, String table){
        // ...
    }

}
Run Code Online (Sandbox Code Playgroud)


And*_*yle 5

一个List<Object>不是一个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);
Run Code Online (Sandbox Code Playgroud)

因此,不允许在两种不兼容的类型之间进行铸造,因为它会破坏类型安全保证.

你几乎肯定想要声明你的insertAllItemsToDb方法来取一个List<?>而不是一个List<Object>,因为你不关心元素类型是什么,只要它是Object的子类(这是非常真实的).

这应该可以防止您在不可转换的类型之间进行转换,并且通常可以更好地使用.

有关更多信息,请查看Angelika Langer出色的Java Generics常见问题解答中的Wildcard Bounds部分.事实上,如果你还没有,你应该看看整个事情.要带走的一般原则是,在大多数情况下,您应该在用于方法参数的集合上使用通配符 - 如果您同时读取和写入集合(这实际上非常罕见),那么您唯一不会这样做.