抱歉标题,因为我找不到更好的标题,所以任何编辑都将不胜感激。
考虑这些课程:
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类进行serillize,并且Jackson无法在运行时确定实际的类型和对象而无需其他信息超级课程。
答案 0 :(得分:2)
原因是返回类型可能是covariant。
在覆盖方法时,您始终可以返回更具体的类型(即子类型)。一个更易于理解的例子如下:
class NumberProvider {
Number getNumber() { return 1.23; }
}
class IntegerProvider extends NumberProvider {
// Returning a more specific type when overriding:
@Override
Integer getNumber() { return 42; }
}
Collection<DashletSetting>
类型是Collection<? extends GlobalDashletSetting>
的正确子类型。请参阅泛型常见问题解答中有关Which super-subtype relationships exist among instantiations of generic types?的部分。
对于setter,这不起作用。它不起作用的简短原因是:它不是类型安全的。很容易找到违反类型安全的地方的例子,虽然乍一看似乎有点做作:
// 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 允许更具体的类型方法,然后可能违反类型安全。
答案 1 :(得分:1)
因为它有不同的签名。
Collection<DashletSetting>
不是Collection<? extends GlobalDashletSetting>
你需要覆盖确切的签名,而不是它的一部分。
如果您的方法需要Object
,则无法使用String
甚至String
扩展Object
在你的情况下,Collection<DashletSetting>
和Collection<? extends GlobalDashletSetting>
实际上是不同的类,你必须覆盖同一个类。
getter正在工作,因为它具有相同的签名(相同的方法名称和没有参数),这不是setter中的情况
答案 2 :(得分:1)
因为覆盖方法不能限制输入变量的范围。原始方法可以接受扩展GlobalDashletSetting
类的任何内容,但是,覆盖方法只限于GlobalDashletSetting
类的一个子类