Java 使用具有公共上界的单个函数重写多个泛型函数

Java 使用具有公共上界的单个函数重写多个泛型函数,java,generics,overriding,upperbound,Java,Generics,Overriding,Upperbound,我有两个不同的接口 接口列集{ V getValue(I列); } 接口参数集{ V getValue(I值); } 其中,类型列和参数只是标记接口,用于停止列s应在参数s处使用,反之亦然。因此,在幕后,我希望有一个单独的类来实现它们,如下所示: @Override public <V, I extends Column & Input<V>> V getValue(I value) { return doGetValue(value); } @Ove

我有两个不同的接口

接口列集{
V getValue(I列);
}
接口参数集{
V getValue(I值);
}
其中,类型
参数
只是标记接口,用于停止
s应在
参数
s处使用,反之亦然。因此,在幕后,我希望有一个单独的类来实现它们,如下所示:

@Override
public <V, I extends Column & Input<V>> V getValue(I value) {
    return doGetValue(value);
}

@Override
public <V, I extends Parameter & Input<V>> V getValue(I value) {
    return doGetValue(value);
}

private <V, I extends Input<V>> V doGetValue(I value) { ... }
@Override
public Object getValue(Input value) { ... }
类ObjectSet实现列集、参数集{
@覆盖公共V getValue(I输入){
...
}
}
从逻辑上看,它似乎是
ObjectSet.getValue
应该是
ColumnSet.getValue
ParameterSet.getValue
的有效重写,因为它将任何
Input
作为参数,该参数的上限由
Column&Input
Parameter&Input
确定。但是,Java 9不认为它覆盖了它们中的任何一个,报告类型为ObjectSet的方法getValue()必须覆盖或实现一个泛型超类型方法

这是Java中泛型的局限性还是我遗漏了一些基本的东西

(显然,我无法在
ObjectSet
中创建两个单独的方法,因为它们具有相同的擦除,这让我可以在我试图避免的接口中为两个
getValue
方法指定不同的名称。),如果
m1
的签名是
m2
签名的子签名,则实例方法
m1
将覆盖另一个实例方法
m2

换句话说,重写方法签名应与重写方法签名或重写方法签名的擦除相同

因此,重写的方法参数不能替换为重写方法中不太特定类型的参数。你可以理解为什么会这样


在您的例子中,
ObjectSet#getValue
签名与
ColumnSet#getValue
签名及其擦除签名不同(
Object getValue(Column Column)
)。这同样适用于
参数集#getValue


正如if所指出的,基方法声明如下:

<V, I extends Column & Input<V>> V getValue(I column);
<V, I extends Parameter & Input<V>> V getValue(I value);
<V, I extends Input<V> & Column> V getValue(I value);
<V, I extends Input<V> & Parameter> V getValue(I value);

由于这两个选项看起来都不好,我建议按以下方式重新设计代码:

public interface Input<R, V> {
    // ...
}
其中
DelegatingObjectSet
是:

abstract class DelegatingObjectSet<R> implements ObjectSet<R> {
    // you can use dependency injection here
    private final ObjectSet<R> delegate = new ObjectSetImpl<>();

    @Override
    public <V> V getValue(Input<R, V> input) {
        return delegate.getValue(input);
    }
}
抽象类DelegatingObjectSet实现ObjectSet{
//您可以在这里使用依赖项注入
private final ObjectSet delegate=new ObjectSetImpl();
@凌驾
公共V getValue(输入){
返回delegate.getValue(输入);
}
}

I通过添加两个方法
V getValue(I列),编译时没有错误
V getValue(I列)
ObjectSet
中。啊,所以在我的原始示例中,我交换了
列/参数
输入
。如果您在任何地方写入
列和输入
参数和输入
,则允许添加这两种方法。如果改为在任何地方写入
Input&Column
和'Input&Parameter',则不允许同时添加这两个方法,因为类型擦除只使用第一个绑定,而不使用第二个绑定。这给了我一个继续的方法,谢谢!我仍然对原始方法不起作用的原因感兴趣。我刚刚意识到如何避免您的问题,并将
对象集
列集
参数集
以及所有其他可以创建的设置集解耦。看看我的答案,我已经更新了。
public class ObjectSetImpl<R> implements ObjectSet<R> {
    @Override
    public <V> V getValue(Input<R, V> input) {
        // ...
    }
}
public interface Column<V> extends Input<Column<?>, V> {}
ObjectSet<Column<?>> columnSet = new ObjectSetImpl<>();
public class ColumnSet extends DelegatingObjectSet<Column<?>> {}
ColumnSet columnSet = new ColumnSet();
abstract class DelegatingObjectSet<R> implements ObjectSet<R> {
    // you can use dependency injection here
    private final ObjectSet<R> delegate = new ObjectSetImpl<>();

    @Override
    public <V> V getValue(Input<R, V> input) {
        return delegate.getValue(input);
    }
}