14

我想要一个 compareTo 方法,它需要一个 Real(一个用于处理任意大和精确的实数的类 [嗯,只要它现在的长度小于 2^31])和一个 compareTo 方法一个对象,但 Java 不让我这样做,而且我没有足够的经验知道为什么。

我只是尝试修改该类以实现 Comparable,并在下面收到这些错误消息。我真的不明白错误消息的含义,但我知道这与我试图为班级提供一些灵活性的可怕方式有关,因为我为我所做的每一种方法提供了所有不同的方法签名,我可以修复它通过删除 compareTo(Object other) 方法,但理想情况下我想保留它。所以我真正要问的是:有没有办法让这些错误消息消失而不删除 compareTo(Object other) 方法,这些错误到底是什么意思?

另外,我知道已经有一些内置的 Java 类,比如 BigInteger 和类似的东西,我试图使用这个类,但我这样做是为了好玩/满足欧拉项目(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

这些是 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())); }

以及构造函数以防万一您需要它们:

  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()); }
4

3 回答 3

14

犯法的方法有:

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

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

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

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

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

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

Real comparedAsReal = new Real(compared);
int result = real.compareTo(comparedAsReal);
于 2013-06-14T20:58:01.377 回答
3

由于您希望能够将Realobject 与进行比较Object,因此您可以将 替换implements Comparable<Real>implements Comparable<Object>。这与Comparable<T>javadoc 说的一致<T> the type of objects that this object may be compared 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())); }
于 2013-06-14T21:00:41.057 回答
1

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

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

这是重现的最小代码:

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

    @Override
    public int compareTo(Real o)
    {
        return 0;
    }       
}
于 2013-06-14T20:59:20.617 回答