Java通配符错误

roy*_*oyB 2 java generics bounded-wildcard

我有一个BaseDao接口,使用hibernate将数据持久化到mysql

public interface BaseDao<T extends Serializable> {
    public void saveAll(Collection<T> objects) throws PersistenceException;
}
Run Code Online (Sandbox Code Playgroud)

我有一个实体类hirechy,他们的基类是BaseActivity(所有扩展可序列化)其中之一:

public class Activity1 extends BaseACtivity{...}
Run Code Online (Sandbox Code Playgroud)

在某些班级我宣布ActivityDao:

 protected abstract ActivityDao<Activity1> createActivityDao1();
Run Code Online (Sandbox Code Playgroud)

和方法:

 private void  persistData(ActivityDao<? extends BaseActivity> activityDao, Collection<? extends BaseActivity> data){
    EntityTransaction transaction = activityDao.getEntityManager().getTransaction();

    try {
        transaction.begin();

        activityDao.saveAll(data);
        transaction.commit();
    }
    catch (HibernateException ex) {
Run Code Online (Sandbox Code Playgroud)

at activityDao.saveAll(data)我得到一个编译时异常:

 Error:(62, 24) java: method saveAll in interface com.matomy.persistence.dao.BaseDao<T>
 cannot be applied to given types;
 required: java.util.Collection<capture#1 of ? extends
 com.matomy.persistence.entity.activities.BaseActivity>
 found: java.util.Collection<capture#2 of ? extends   com.matomy.persistence.entity.activities.BaseActivity>
 reason: actual argument java.util.Collection<capture#2 of ? extends     com.matomy.persistence.entity.activities.BaseActivity>
 cannot be converted to java.util.Collection<capture#1 of ? extends     com.matomy.persistence.entity.activities.BaseActivity> 
 by method invocation conversion
Run Code Online (Sandbox Code Playgroud)

BaseActivity:

public abstract class BaseActivity implements Serializable, Comparable<BaseActivity> {
Run Code Online (Sandbox Code Playgroud)

请帮助谢谢!

罗伊

更新:

private <T extends BaseActivity> void  persistData(ActivityDao<T> activityDao, Collection<T> col){
    EntityTransaction transaction = activityDao.getEntityManager().getTransaction();

    try {
        transaction.begin();

        activityDao.saveAll(col);
        transaction.commit();
    }
    catch (HibernateException ex) {
Run Code Online (Sandbox Code Playgroud)

Roh*_*ain 5

使用具有相同边界的两个有界通配符并不意味着它们是相同的类型.在这种情况下,实际类型参数ActivityDao<? extends BaseActivity>可能与出现的参数不同Collection<? extends BaseActivity>.所以,该saveAll()方法不起作用.

为了进一步详细说明,编译器使用唯一的占位符替换每个通配符出现,该占位符只是捕获该通配符.这意味着,Collection<?>变得Collection<CAP#1 of ?>同样Collection<? extends T>Collection<CAP#1 of ? extends T>.如果Collection<?>再次遇到a,则将替换为Collection<CAP#2 of ?>.

因此,您的方法声明有点类似于:

private void  persistData(ActivityDao<CAP#1-of-? extends BaseActivity> activityDao, Collection<CAP#2-of-? extends BaseActivity> data){
    EntityTransaction transaction = activityDao.getEntityManager().getTransaction();

    try {
        transaction.begin();

        activityDao.saveAll(data);
        transaction.commit();
    }
    catch (HibernateException ex) {
    }
}
Run Code Online (Sandbox Code Playgroud)

其中CAP#1CAP#2是编译器的不同类型参数.当然,该saveAll方法的签名变为如下:

public void saveAll(Collection<CAP#1-of-? extends BaseActivity> objects) throws PersistenceException;
Run Code Online (Sandbox Code Playgroud)

并且因为Collection<T1>Collection<T2>两个不同类型的参数不同,所以方法调用失败.

您可以使用泛型方法来解决此问题:

private <T extends BaseActivity> void persistData(ActivityDao<T> activityDao, Collection<T> data){
Run Code Online (Sandbox Code Playgroud)