在通用超类中实现Comparable <t> </t>

时间:2013-04-26 03:11:50

标签: java generics

我有一个抽象的通用超类,我扩展它来制作具有特定类型ID的具体类:

public abstract class AbstractEntity<I> {
  ...
  private I id;
  private String name;
  ...
}

我创建了这样的具体类:

public class User extends AbstractEntity<Long> {...}

现在我想使具体类与其他自己的实例相比(没有其他类型 - 这应该在编译时强制执行)。默认情况下,compareTo方法应该按名称排序,因此我想将其添加到超类中以避免重复代码。我想出来的唯一方法是使用这个丑陋的构造:

public abstract class AbstractEntity<I,T> implements Comparable<AbstractEntity<I,T>> {
  ...
  private I id;
  private String name;
  ...
  @Override
  public int compareTo(AbstractEntity<I,T> o) {
    ...
  }
}

...

public class User extends AbstractEntity<Long,User> {...}

我认为这很难看,因为现在为了扩展超类,你需要再次重复具体的类名作为自身的类型参数,这是奇怪的和违反直觉的。是否有更优雅的方式来完成我所缺少的同样的事情?

谢谢!

4 个答案:

答案 0 :(得分:7)

您正在寻找的是“自我类型”,但这在Java中无法实现。你最接近的是使用一个递归绑定的类型参数,该参数应该是自我类型:

public abstract class AbstractEntity<I, E extends AbstractEntity<I, E>> implements Comparable<E> {
    ...
    private I id;
    private String name;
    ...
    public final String getName() {
        return name;
    }
    ...
    @Override
    public int compareTo(E otherEntity) {
        final String otherName = otherEntity.getName();
        ...
    }
}

public final class User extends AbstractEntity<Long, User> { }

我会建议不要使用这种模式,因为它很容易混淆,很容易被滥用。例如:

public final class EvilUser extends AbstractEntity<Long, AnotherUser> { }

我的建议:坚持在个人实体的基础上实施Comparable

答案 1 :(得分:2)

没有。这就是你应该怎么做的。在类似这样的情况下,将类本身放在参数描述中实际上是正常的事情。

答案 2 :(得分:1)

这就是你要找的东西

public abstract class AbstractEntity<I> implements
        Comparable<AbstractEntity<I>> {
    private I id;

    @Override
    public int compareTo(AbstractEntity<I> o) {

        if (o != null && !o.getClass().equals(getClass())) {
            throw new IllegalArgumentException("Unsupported instance type "
                    + o.getClass());
        }

        return 0;
    }

}

public class User extends AbstractEntity<Long> {
}

答案 3 :(得分:0)

  

现在我想使具体类与其他实例相媲美   他们自己(没有其他类型 - 这应该在编译时强制执行   时间)。

为什么呢?泛型不适合你进行任意限制。泛型仅用于强制执行类型安全(即消除强制类型转换;避免使用ClassCastException)。任意要求它不能与其他类型相比,不能用于类型 - 安全目的,因此无法完成。

如果比较不依赖于任何子类功能,那么AbstractEntity<I>可与所有AbstractEntity<I>相媲美,在这种情况下,它应该像这样声明:

public abstract class AbstractEntity<I> implements Comparable<AbstractEntity<I>>
  

这里的问题是具体类可以与之相媲美   编译时具有相同ID类型的任何其他具体类

那又怎样?比较完全是类型安全的。如果您不想将一个具体类别与另一个具体类别进行比较,那么请不要。如果其他人想要将一个具体的类别与另一个具体类别进行比较,那么对他为什么这对你很重要?

P.S。您发布的代码public abstract class AbstractEntity<I,T> implements Comparable<AbstractEntity<I,T>>也没有强制要求一个类仅与自身进行比较,因为无法保证类必须将其自身扩展为第二个参数。