很抱歉有这个标题,因为我找不到更好的标题,所以如果有任何编辑,我们将不胜感激。
考虑以下类别:
public interface GlobalDashlet {
public Collection<? extends GlobalDashletSetting> getSettings();
public void setSettings(Collection<? extends GlobalDashletSetting> settings);
}
public class Dashlet implements GlobalDashlet {
private Collection<DashletSetting> settings;
public Collection<DashletSetting> getSettings(){
return settings;
}
//This Wont Work
public void setSettings(Collection<DashletSetting> settings) {
this.settings = settings;
}
//This Will Work
public Collection<DashletSetting> getSettings(){
return settings;
}
}
public class DashletSetting implements GlobalDashletSetting {
}
为什么重写setter方法(我指的是我所做的方式)不起作用(dashlet类抱怨未实现的方法),而重写getter方法起作用?
我该怎么修?我也需要能够实现setter方法(就像我覆盖getter方法的方式一样),因为我必须用jackson mapper将Dashlet类序列化,并且如果没有关于超类的额外信息,jackson无法在运行时确定和对象的实际类型。
在重写方法时,您总是可以返回更具体的类型(即子类型)。一个更容易理解的例子如下:
class NumberProvider {
Number getNumber() { return 1.23; }
}
class IntegerProvider extends NumberProvider {
// Returning a more specific type when overriding:
@Override
Integer getNumber() { return 42; }
}
类型CCD_ 1是CCD_。请参阅关于泛型类型的实例化之间存在哪些超子类型关系的部分?在Generics常见问题解答中。
对于二传手来说,这是行不通的。它不起作用的简短原因是:它不是类型安全的。一个违反类型安全的例子很容易找到,尽管乍一看可能有点做作:
// This is the interface as it was defined:
public interface GlobalDashlet {
public void setSettings(Collection<? extends GlobalDashletSetting> settings);
}
public class Dashlet implements GlobalDashlet {
// Assume this was working:
public void setSettings(Collection<DashletSetting> settings) {
// Then you could add a "DashletSetting" here:
settings.add(new DashletSetting());
}
}
// But someone who CALLED this method may not have given it
// a Collection<DashletSetting>, but maybe a collection
// like Collection<SpecialGlobalDashletSetting>:
Collection<SpecialGlobalDashletSetting> settings = ...;
GlobalDashlet dashlet = new Dashlet();
// Based on the method signature that was defined in the interface,
// this would be possible:
dashlet.setSettings(settings);
// Now, the "settings" collection WOULD contain a simple "DashletSetting",
// although it should only contain "SpecialGlobalDashletSetting" instances
// This would cause a ClassCastException sooner or later
这个例子看起来可能有点令人困惑。同样,Number
和Integer
等"简单"类型更直观,但归根结底是同一个问题:如果setter方法允许使用更具体的类型,则可能会违反类型安全性。
因为被重写的方法不能限制输入变量的范围。原始方法可以接受任何扩展GlobalDashletSetting
类的东西,但被重写的方法仅限于GlobalDashletSetting
类的一个子类
因为它有不同的签名。
Collection<DashletSetting>
不是Collection<? extends GlobalDashletSetting>
你需要覆盖确切的签名,而不是它的一部分。
如果您有采用Object
的方法,即使Collection<DashletSetting>
1扩展了Object
,也不能用采用String
的方法覆盖它
在您的情况下,Collection<DashletSetting>
和Collection<? extends GlobalDashletSetting>
实际上是不同的类,您必须用同一个类重写。
getter正在工作,因为它具有相同的签名(相同的方法名称,没有参数),而setter