可以通过Java泛型类型系统强制执行自然排序吗?

时间:2017-01-20 22:51:04

标签: java generics types

TreeSet(Collection<? extends E> c)构造函数定义为:

  

构造一个新的树集,其中包含指定集合中的元素,并根据其元素的自然顺序进行排序。插入集合的所有元素都必须实现Comparable接口。此外,所有这些元素必须是可相互比较的:e1.compareTo(e2)不得为集合中的任何元素e1和e2抛出ClassCastException。

E Collection<? extends E>中的Comparable是否可以通过语法强制执行INSERT INTO suppliers (supplier_id, supplier_name, supplier_type) SELECT account_no, name, 3 FROM customers WHERE city = 'San Diego'; ?在上面的JavaDoc中,这个检查推迟到执行时间......

3 个答案:

答案 0 :(得分:3)

是的,但不是建造者;您必须公开一个工厂方法,该方法可以对集合类型施加超出整个类强加的约束。例如,他们可以写

public class TreeSet<E> { ...
  public static <E extends Comparable<? super E>> TreeSet<E>
      create(Collection<? extends E> collection) {
    TreeSet<E> set = new TreeSet<E>();
    set.addAll(collection);
    return set;
  }
  ...
}

答案 1 :(得分:1)

您可以使用这样的工厂方法使您的项目需要这个:

public static <T extends Comparable<? super T>> SortedSet<T> safeSortedSet() {
    return new TreeSet<T>();
}

然后是代码:

Set<String> pass = safeSortedSet();
Set<Foo> fail = safeSortedSet();

第二行产生编译错误:

  

错误:(99,38)java:不兼容的类型:推理变量T具有不兼容的边界
      平等约束:Test.Foo
      上限:java.lang.Comparable

答案 2 :(得分:0)

来自 Tavian Barnes 评论:

  

他们可以完成课程TreeSet<E extends Comparable<? super E>>,但是你不可能将自定义比较器用于不可订购的类型。我无法想出一种只在一个构造函数上强制执行此操作的好方法

因此可以使用<E extends Comparable<? super E>>语法,但遗憾的是,每个通用extends / super语法都会对使用E的任何其他类型声明进行最终限制。

如果TreeSet查看Creating a TreeSet with a non-Comparable class: why a run-time exception, rather than compile-time error?

感谢所有帮助解答的人!