为什么在这种情况下,覆盖Setter方法不起作用



很抱歉有这个标题,因为我找不到更好的标题,所以如果有任何编辑,我们将不胜感激。

考虑以下类别:

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

这个例子看起来可能有点令人困惑。同样,NumberInteger等"简单"类型更直观,但归根结底是同一个问题:如果setter方法允许使用更具体的类型,则可能会违反类型安全性。

因为被重写的方法不能限制输入变量的范围。原始方法可以接受任何扩展GlobalDashletSetting类的东西,但被重写的方法仅限于GlobalDashletSetting类的一个子类

因为它有不同的签名。

Collection<DashletSetting>不是Collection<? extends GlobalDashletSetting>

你需要覆盖确切的签名,而不是它的一部分。

如果您有采用Object的方法,即使Collection<DashletSetting>1扩展了Object ,也不能用采用String的方法覆盖它

在您的情况下,Collection<DashletSetting>Collection<? extends GlobalDashletSetting>实际上是不同的类,您必须用同一个类重写。

getter正在工作,因为它具有相同的签名(相同的方法名称,没有参数),而setter

中的情况并非如此

最新更新