泛型类型多态混淆?

时间:2012-09-26 03:17:00

标签: java generics polymorphism

我有一个像这样的抽象工厂:

public abstract class DAOFactory {
    public abstract EntryDAO<EntryDTO> getEntryDAO();
    ...
}

使用我的DAO和DTO界面:

public interface EntryDTO extends GenericDTO {
}

public interface EntryDAO<T extends EntryDTO> extends GenericDAO<T, Serializable> {  
}

我的实施如下:

public class EntryDTOImpl implements EntryDTO {
}

public class EntryDAOImpl<T extends EntryDTO> extends GenericDaoImpl<EntryDTOImpl, ObjectId> 
 implements EntryDAO<T> {
}

现在,如果我创建一个工厂并覆盖getEntryDAO方法,如下所示:

public class MyDAOFactory extends DAOFactory {   
    @Override
    public EntryDAO<EntryDTO> getEntryDAO() {
        try {
            return new EntryDAOImpl<EntryDTOImpl>();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

我收到编译时错误:

  

类型不匹配:无法从EntryDAOImpl转换为EntryDAO

修改

我已经更新了我的抽象工厂:

public abstract <T extends EntryDTO> EntryDAO<T> getEntryDAO();

并改变了我的工厂实施:

@Override
public <T extends EntryDTO> EntryDAO<T> getEntryDAO() {
    try {
        return new EntryDAOImpl<EntryDTOImpl>();
    } catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

现在我收到了编译时错误:

  

Type mismatch: cannot convert from EntryDAOImpl<EntryDTOImpl> to EntryDao<T>

3 个答案:

答案 0 :(得分:2)

以这种方式定义抽象方法(注意?而不是T):

public abstract EntryDAO<? extends EntryDTO> getEntryDAO(); //should work for you

我按照我理解的方式重新创建了方案:subclass1<subclass2>作为interface1<interface2>

返回

例如,这很有效:

public static List<? extends CharSequence> dostuff1() { 
    return new ArrayList<String>();
}

但这不起作用:

public <B extends CharSequence> List<B> dostuff2() {
    return new ArrayList<String>();
}

这会产生相同的编译时错误:Type mismatch: cannot convert from ArrayList<String> to List<B>

答案 1 :(得分:1)

发生这种情况的原因是您尝试返回的EntryDaoImpl<EntryDTOImpl>EntryDao<EntryDTOImpl>的子类型,而不是EntryDao<EntryDTO>的子类型,这是getEntryDao的返回类型方法

<强>解决方案:

我相信您想要将EntryDAO<? extends EntryDTO>方法的返回类型更改为

{{1}}。

答案 2 :(得分:1)

只需将返回类型从EntryDao<T>更改为EntryDao<? extends T>即可。这样就可以了:

@Override
public <T extends EntryDto> EntryDao<? extends T> getEntryDao() {
    try {
        return new EntryDAOImpl<EntryDTOImpl>();
    } catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return dao;
}

现在作为理由,假设EntryDao<T>有返回T的方法

T load(Serializable id);

和接受T的方法

void save(T t);

现在假设PersonDTO extends EntryDTOCarDTO extends EntryDTO

如果EntryDao<EntryDTO>可以EntryDao<EntryDTOImpl>分配,EntryDao<PersonDTO>也可以分配EntryDao<CarDTO>EntryDao<EntryDTO> x = new EntryDao<PersonDTO>(); // currently this is a compile time error

然后你可以这样做:

x.save(new CarDTO());   // a run time error, because x can only save Persons, not Cars

如果这是合法的,你可以这样做:

EntryDao<? extends EntryDTO>

但是T是什么?只有EntryDao包含所有save(T) - 接受{{1}}等方法。