java 实现 Comparable,compareTo 名称冲突:“具有相同的擦除,但都不覆盖另一个”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17116845/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 01:02:48  来源:igfitidea点击:

Implementing Comparable, compareTo name clash: "have the same erasure, yet neither overrides the other"

javagenericsoverridingcomparableerasure

提问by Jxek

I'd like to have a compareTo method that takes a Real (a class for working with arbitrarily large and precise real numbers [well, as long as it's less than 2^31 in length at the moment]) and a compareTo method that takes an Object, but Java isn't letting me and I'm not experienced enough to know why.

我想要一个使用 Real 的 compareTo 方法(一个用于处理任意大且精确的实数的类[好吧,只要它目前的长度小于 2^31])和一个 compareTo 方法一个对象,但 Java 不允许我这样做,而且我的经验不足,不知道为什么。

I just tried to modify the class to implement Comparable and I got these error messages below. I don't really understand what the error messages mean but I know it's got something to do with the horrible way I'm trying to give the class some flexibility with all the different method signatures for every single method I make, and I can fix it by removing the compareTo(Object other) method, but I would ideally like to keep it. So what I'm really asking is: Is there a way to make these error messages disappear without removing the compareTo(Object other) method and what exactly do these errors mean?

我只是尝试修改该类以实现 Comparable,并且在下面收到了这些错误消息。我真的不明白错误消息的含义,但我知道这与我试图通过我制作的每个方法的所有不同方法签名为类提供一些灵活性的可怕方式有关,我可以修复它通过删除 compareTo(Object other) 方法,但我希望保留它。所以我真正要问的是:有没有办法在不删除 compareTo(Object other) 方法的情况下使这些错误消息消失,这些错误究竟意味着什么?

Also, I know there are already some built-in Java classes like BigInteger and things like that for what I'm trying to use this class for but I'm doing it for fun/satisfaction for use with Project Euler (https://projecteuler.net/).

另外,我知道已经有一些内置的 Java 类,比如 BigInteger 和类似的东西,我想用这个类来做什么,但我这样做是为了好玩/满意,以便与 Project Euler 一起使用(https:// projecteuler.net/)。

Jake@Jake-PC /cygdrive/c/Users/Jake/Documents/Java/Mathematics
$ javac Real.java
Real.java:377: error: name clash: compareTo(Real) in Real overrides a method whose erasure is the same as another method, yet neither overrides the other
  public int compareTo(Real other)
             ^
  first method:  compareTo(Object) in Real
  second method: compareTo(T) in Comparable
  where T is a type-variable:
    T extends Object declared in interface Comparable
Real.java:440: error: name clash: compareTo(Object) in Real and compareTo(T) in Comparable have the same erasure, yet neither overrides the other
  public int compareTo(Object other)
             ^
  where T is a type-variable:
    T extends Object declared in interface Comparable
2 errors

These are the compareTo methods:

这些是 compareTo 方法:

  @Override
  public int compareTo(Real other)
  {
    // Logic.
  }
  public int compareTo(char givenValue) 
  { return compareTo(new Real(givenValue)); }
  public int compareTo(char[] givenValue) 
  { return compareTo(new Real(givenValue)); }
  public int compareTo(char[] givenValue, int offset, int count) 
  { return compareTo(new Real(givenValue, offset, count)); }
  public int compareTo(double givenValue) 
  { return compareTo(new Real(givenValue)); }
  public int compareTo(float givenValue) 
  { return compareTo(new Real(givenValue)); }
  public int compareTo(int givenValue) 
  { return compareTo(new Real(givenValue)); }
  public int compareTo(long givenValue) 
  { return compareTo(new Real(givenValue)); }
  public int compareTo(Object other) 
  { return compareTo(new Real(other.toString())); }

and the constructors just in case you need them:

和构造函数,以防万一你需要它们:

  public Real(String givenValue)
  {
    // Logic.
  }
  public Real(char givenValue) 
  { this(String.valueOf(givenValue)); }
  public Real(char[] givenValue) 
  { this(String.valueOf(givenValue)); }
  public Real(char[] givenValue, int offset, int count) 
  { this(String.valueOf(givenValue, offset, count)); }
  public Real(double givenValue) 
  { this(String.valueOf(givenValue)); }
  public Real(float givenValue) 
  { this(String.valueOf(givenValue)); }
  public Real(int givenValue) 
  { this(String.valueOf(givenValue)); }
  public Real(long givenValue) 
  { this(String.valueOf(givenValue)); }
  public Real(Object other) 
  { this(other.toString()); }

采纳答案by Paul Bellora

The offending methods are:

违规方法是:

@Override
public int compareTo(Real other) { ... }

public int compareTo(Object other) { ... }

These methods have the same erasure, meaning that once the compiler strips out generic type information, there will no longer be a way to differentiate them at runtime.

这些方法具有相同的擦除,这意味着一旦编译器去除了泛型类型信息,将不再有在运行时区分它们的方法。

Your options are to either remove the compareTo(Object other)overload, or for Realto implement Comparable<Object>.

您的选择是删除compareTo(Object other)重载,或Real实现Comparable<Object>.

Since it looks like the implementations of all your compareTooverloads just instantiate a new Realand pass it to compareTo(Real), I'd suggest removing them and leaving that conversion up to the caller:

由于看起来所有compareTo重载的实现只是实例化一个 newReal并将其传递给compareTo(Real),我建议删除它们并将该转换留给调用者:

Real real = ...;
Object compared = ...;

Real comparedAsReal = new Real(compared);
int result = real.compareTo(comparedAsReal);

回答by Guillaume Darmont

Since you want to be able to compare Realobject to Object, you may just replace the implements Comparable<Real>with implements Comparable<Object>. This would be consistent with Comparable<T>javadoc which says that <T> the type of objects that this object may be compared to.

既然你希望能够比较Real对象Object,你可能只是更换implements Comparable<Real>implements Comparable<Object>。这将与Comparable<T>javadoc一致,它说<T> the type of objects that this object may be compared to.

Then you just have to change your current code to :

然后,您只需将当前代码更改为:

// No more @Override
public int compareToReal(Real other)
{
  // Logic.
}
public int compareTo(char givenValue) 
{ return compareToReal(new Real(givenValue)); }
public int compareTo(char[] givenValue) 
{ return compareToReal(new Real(givenValue)); }
public int compareTo(char[] givenValue, int offset, int count) 
{ return compareToReal(new Real(givenValue, offset, count)); }
public int compareTo(double givenValue) 
{ return compareToReal(new Real(givenValue)); }
public int compareTo(float givenValue) 
{ return compareToReal(new Real(givenValue)); }
public int compareTo(int givenValue) 
{ return compareToReal(new Real(givenValue)); }
public int compareTo(long givenValue) 
{ return compareToReal(new Real(givenValue)); }
@Override
public int compareTo(Object other) 
{ return compareToReal(new Real(other.toString())); }

回答by Pragmateek

This is a side effect of Java generics type-erasure.

这是Java 泛型类型擦除的副作用。

You are implementing a generic interface, Comparable, but this its unique method, once generic type erased will become compareTo(Object), hence it clashes with your own compareTo(Object).

您正在实现一个通用接口Comparable,但这是其独特的方法,一旦擦除通用类型将变为compareTo(Object),因此它与您自己的compareTo(Object)发生冲突。

Here is a minimal code to reproduce:

这是重现的最小代码:

class Real implements Comparable<Real>
{
    public int compareTo(Object o)
    {
        return 0;
    }

    @Override
    public int compareTo(Real o)
    {
        return 0;
    }       
}