如何将这部分C#泛型转换为Java

时间:2019-11-17 16:47:34

标签: java c# generics

给出以下C#代码,如何将其转换为Java?

public class Stop : IComparable<Stop>
{
    public int CompareTo(Stop other) { ... }
}

public class Sequence<T> : IEnumerable<T>
    where T : IComparable<T>
{
    public IEnumerator<T> GetEnumerator() { ... }

    IEnumerator IEnumerable.GetEnumerator() { ... }
}

public class Line<T> : Sequence<T>, IComparable<Line<T>>
    where T : Stop
{
    public int CompareTo(Line<T> other) { ... }
}

我很难将Line类的定义转换为Java。我的第一次尝试是:

public class Line<T extends Stop> extends Sequence<T> implements Comparable<Line<T>> { ... }

但是,编译器针对extends Sequence<T>报告以下错误:

Error: type argument T is not within bounds of type-variable T

将定义更改为

public class Line<T extends Comparable<T>> extends Sequence<T> implements Comparable<Line<T>> { ... }

修复了该错误,但不能准确反映其意图:我想强制所有与Line一起使用的类型参数必须是Stop的子类型。使用T extends Comparable<T>将允许实现接口的任意类型。

我不明白该错误的原因。是否有某种方法可以表达这种关系而不改变类型的结构,或者这是Java泛型的局限性?

编辑:访问https://www.onlinegdb.com/S1u9wclnH以查看我的尝试的精简版本。

1 个答案:

答案 0 :(得分:1)

问题在于您对class Sequence的定义。

public class Sequence<T> : IEnumerable<T>
    where T : IComparable<T> { ... }

此C#类利用IComparable是反变量的事实,因此C#类不需要完全T: IComparable<T>,但是如果T与它的基类之一。因此,即使使用从T派生的类实例化了Stop,该代码仍然有效。

Java没有声明站点差异,但是有使用站点差异(通配符)。无法为Sequence派生的类实例化Java Stop类,但可以实例化Line类。因此出现编译器错误。

要解决此问题,每当在边界中使用Comparable时,都需要将C#的声明站点差异转换为Java的通配符:

class Sequence<T extends Comparable<? super T>> implements Iterable<T> { ... }