Java 实施可比<;T>;在泛型超类中

Java 实施可比<;T>;在泛型超类中,java,generics,Java,Generics,我有一个抽象的泛型超类,我将其扩展为具有特定类型ID的具体类: public abstract class AbstractEntity<I> { ... private I id; private String name; ... } 公共类用户扩展抽象实体{…} 我认为这很难看,因为现在为了扩展超类,您需要再次将具体的类名作为其自身的类型参数来重复,这既奇怪又违反直觉。有没有更优雅的方式来完成我所错过的事情 谢谢 不,这是你应该做的。在这种情况下,将类本身放

我有一个抽象的泛型超类,我将其扩展为具有特定类型ID的具体类:

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

公共类用户扩展抽象实体{…}
我认为这很难看,因为现在为了扩展超类,您需要再次将具体的类名作为其自身的类型参数来重复,这既奇怪又违反直觉。有没有更优雅的方式来完成我所错过的事情


谢谢

不,这是你应该做的。在这种情况下,将类本身放入参数描述中实际上是一件正常的事情。

这就是您要寻找的吗

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> {
}
公共抽象类AbstractEntity实现
可比{
私人身份证;
@凌驾
公共整数比较(抽象实体o){
如果(o!=null&&!o.getClass().equals(getClass())){
抛出新的IllegalArgumentException(“不支持的实例类型”
+o.getClass());
}
返回0;
}
}
公共类用户扩展抽象实体{
}

您需要的是“self类型”,但这在Java中是无法实现的。最接近的方法是使用递归绑定的类型参数,该参数被认为是self类型:

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> { }
公共抽象类AbstractEntity实现可比较{
...
私人身份证;
私有字符串名称;
...
公共最终字符串getName(){
返回名称;
}
...
@凌驾
公共整数比较(E其他实体){
最后一个字符串otherName=otherEntity.getName();
...
}
}
公共最终类用户扩展抽象实体{}
不过我建议不要使用这种模式,因为它很混乱,很容易被滥用。例如:

public final class EvilUser extends AbstractEntity<Long, AnotherUser> { }
public final类用户扩展抽象实体{}
我的建议是:只需坚持在单个实体的基础上实施
compariable

现在我想让具体类与其他实例相比较 它们本身(而不是其他类型——这应该在编译时强制执行) 时间)

为什么??泛型不允许您进行任意限制。泛型仅用于强制类型安全(即消除类型转换;避免ClassCastException)。任意要求其不可与其他类型进行比较不符合类型安全目的,因此无法做到

如果比较不依赖于任何子类特性,则
AbstractEntity
可与所有
AbstractEntity
进行比较,在这种情况下,应该这样声明:

public class User extends AbstractEntity<Long> {...}
public abstract class AbstractEntity<I> implements Comparable<AbstractEntity<I>>
公共抽象类抽象实体实现可比性

这里的问题是,具体类与 编译时具有相同ID类型的任何其他具体类

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


p、 您发布的代码,
公共抽象类AbstractEntity实现了Comparable
也没有强制要求一个类只与自身进行比较,因为不能保证类必须将其自身作为第二个参数进行扩展。

这里的问题是,具体类在编译时可以与具有相同ID类型的任何其他具体类进行比较,并将检查推迟到运行时。我希望具体类只能与完全相同类的其他类进行比较,并在编译时强制执行,以避免不必要的运行时错误。如果没有某种支持证据,很难对“你不能”类型的答案“竖起大拇指”。你能给出一个类似问题的链接吗?这是共识所在?@AlvinThompson-很容易找到支持这个答案的证据。请查看API文档中实现类似功能的任何类:<代码>字节实现可比较的@jahroy-这不是一回事;在这种情况下,具体类实现了可比性。如果有什么区别的话,那就是Compariable应该由具体类实现的论点,而不是这是不可能的证据。@AlvinThompson-好的。。。那很好。我提供了证据来支持“在这种情况下做一件正常的事情”不支持某些事情是不可能的。我通常会说您应该在子类中实现Comparable,但您已经在Paul的答案下的注释中解释了为什么这不是最佳的(或合理的)。祝你好运从技术上讲,一个人可以“打破隐含的契约”,创建一个具体的类,该类与其他类类似,比如“类Foo扩展了抽象实体”,但我并不担心人们会不厌其烦地写垃圾。有什么理由你必须使用
Comparable
而不是
Comparator
Comparator
方法似乎更适合用于可继承类型。如果您需要能够在没有
比较器
的情况下比较项目,但您可以控制所讨论的类型,那么定义一个接口也可能会有所帮助,该接口允许向对象请求适合其使用的
比较器
。如果有一个
比较器
可以处理数组中的所有项,那么即使这些项是不同类型的,也可以对数组进行干净的排序。@supercat-主要是因为它需要较少的客户端更改才能获得好处。如果使用比较器,客户端代码必须获取比较器并显式使用它(通过创建使用它的集合或将它传递给排序函数)。他们必须在任何他们想分类的地方这样做。这样,如果客户机代码碰巧将这种类型的对象放在自然排序的集合中(或者它们调用自然排序函数),它将
public final class EvilUser extends AbstractEntity<Long, AnotherUser> { }
public abstract class AbstractEntity<I> implements Comparable<AbstractEntity<I>>