鉴于以下示例,为什么我能够在List<? extends IConfigUser>
中将返回类型List<ConfigUser>
覆盖为getUserList()
,但不能对setUserList()
的参数执行相同操作?< / p>
在这种情况下,ConfigUser
是否被视为IConfigUser
的超类型?
public class Test {
public interface IConfigUser {
}
public interface IConfig {
public List<? extends IConfigUser> getUserList();
public void setUserList(List<? extends IConfigUser> list);
}
public class ConfigUser implements IConfigUser {
}
// The type Test.Config must implement the inherited abstract method
// Test.IConfig.setUserList(List<? extends Test.IConfigUser>)
public class Config implements IConfig {
@Override
public List<ConfigUser> getUserList() {
return null;
}
// The method setUserList(List<ConfigUser> list) of type Test.Config
// must override or implement a supertype method
@Override
public void setUserList(List<ConfigUser> list)
{
}
}
}
答案 0 :(得分:2)
您可以通过向IConfig
添加通用类型参数来实现目标:
public class Test {
public interface IConfigUser {
}
public interface IConfig<T extends IConfigUser> {
public List<T> getUserList();
public void setUserList(List<T> list);
}
public class ConfigUser implements IConfigUser {
}
public class Config implements IConfig<ConfigUser> {
@Override
public List<ConfigUser> getUserList() {
return null;
}
@Override
public void setUserList(List<ConfigUser> list)
{
}
}
}
答案 1 :(得分:2)
您可以在覆盖中返回更具体的类型,但不能要求接受更具体的类型。摆脱泛型,您可以使用返回Object
的方法覆盖返回String
的方法,但是您无法覆盖接受Object
参数的方法并接受方法一个String
参数。
这一切都是为了使呼叫者兼容。考虑:
IConfig config = new Config();
List<SomeOtherConfigUser> list = new ArrayList<SomeOtherConfigUser>();
list.add(new SomeOtherConfigUser());
config.setUserList(list);
糟糕 - 您的Config.setUserList
期望每个元素都是ConfigUser
,而不是SomeOtherConfigUser
。
答案 2 :(得分:1)
由于协方差,您可以返回(“specialize”)getUserList()
的返回类型,即如果您在IConfig
引用上调用该方法,您所知道的就是您将得到List<? extends IConfigUser>
1}}和List<ConfigUser>
是 List<? extends IConfigUser>
,因此满足要求。
如果您在Config
引用上调用该信息,则信息更具体,但仍满足基本要求。
使用setUserList(...)
情况有所不同:它允许您传递 List<? extends IConfigUser>
的任何“子类”,其中可以 a {{1但它也可能是其他东西,例如List<ConfigUser>
。
顺便说一下,因为你不知道List<SomeConfigUser>
中list
的具体通用参数,编译器也只允许你从该列表中读取,从不添加它 - 原因与上面:你不知道你得到了什么以及是否允许添加setUserList(List<ConfigUser> list)
,因为该列表只允许添加ConfigUser
个实例。