以下内容给出了此错误:
public class Account
{
...
}
public class DB_Account extends Account implements DBObject
{
...
}
public class Cache<E extends DBObject>
{
protected Map<Long,E> m_contents;
...
public Collection<E> values()
{
return m_contents.values();
}
}
public class DB_Imp implements Database
{
protected Cache<DB_Account> m_accounts;
...
@Override
public Collection<Account> getAccounts()
{
if (m_accounts.isValid())
/* Compiler gives error here */
return m_accounts.values();
...
}
}
我目前通过在DB_Imp
的调用周围添加Collections.class.cast()
并添加accounts.values()
来解决@SuppressWarnings
类中的编译错误。肯定有更好的办法。另一种方法是将Cache类修改为:
@SuppressWarnings("unchecked")
public <T> Collection<T> values()
{
return Collections.class.cast(m_contents.values());
}
答案 0 :(得分:1)
问题是你试图将Collection<DB_Account>
作为Collection<Account>
返回编译器不会让你。 Collection
不是协变的,因此Collection<DB_Account>
不是Collection<Account>
的子类型。
解决此问题的方法是将values
中的方法Database
修改为:
Collection<? extends Account> values();
修改强> 如果你不能做出改变,我会做的是:
@Override
public Collection<Account> getAccounts() {
if (m_accounts.isValid())
return Collections.unmodifiableCollection(m_accounts.values());
...
}
这会使用正确的参数类型(values()
)创建Collection<Account>
的不可修改的视图。它为您提供额外的安全性(在运行时),您的Cache
无法通过客户端代码进行修改。 values()
会返回Cache
地图的视图,因此呼叫getAccounts()
的人对其进行的每次更改都会反映在Cache
上。这是你通常想要避免的事情。
答案 1 :(得分:0)
首先看一下错误。这是说:
Cache<DB_Account> m_accounts
,方法调用m_accounts.values()
会返回Collection<DB_Account>
。getAccounts()
返回Collection<Account>
Collection<Account>
不是Collection<DB_Account>
的超类型,因此编译器无法转换它们。这是完全正确和预期的。
X
Y
Foo<Y>
不是Foo<X>
这是Java的泛型中的一个关键概念,值得理解。你应该阅读The Java Tutorials > Generics, Inheritance and Subtypes。
如果不了解确切的背景,很难提出解决方案。如果您能够更改Database
界面,一种可能的方法是更改getAccounts
以使用通配符
public Collection<? extends Account> getAccounts();
然而,这只会让你从退回的Collection
中获取项目,而不是将它们设置为它(也许这就是你想要的)。要了解您应该阅读"Upper Bounded Wildcards"和"Guidelines for Wildcard Use"的原因。