【问题标题】:Can't TreeSet check for comparator objects at compile-time?TreeSet 不能在编译时检查比较器对象吗?
【发布时间】:2019-05-04 09:54:47
【问题描述】:

当使用默认构造函数(无参数)在 Java 中创建类 TreeSet 的实例并添加两个未实现 Comparator 接口的类对象时,该对象将引发运行时异常。这个检查可以在编译时实现吗?

我已经尝试了以下代码:

Dummy.java

public class Dummy {
}

TreeSetTest.java

import java.util.TreeSet;

public class TreeSetTest {

    public static void main(String[] argv) {
        TreeSet<Dummy> treeSet = new TreeSet<>();
        treeSet.add(new Dummy());
        treeSet.add(new Dummy());
    }
}

编译器在创建 TreeSet 时应该报错,因为它没有实现 Comparable。

【问题讨论】:

  • TreeSet 早于泛型,需要向后兼容。
  • @user207421 为了强制执行,需要进行哪些更改? (给n个源代码link

标签: java class oop interface


【解决方案1】:

如果TreeSet() 构造函数不是公开的,您可以在编译时检查它,使用工厂方法,如下所示:

public static <E extends Comparable<? super E>> TreeSet<E> create() {
  return new TreeSet<>();
}

您只能使用自然可比的类型参数来调用它:

TreeSet<String> a = TreeSet.create(); // ok
TreeSet<Object> b = TreeSet.create(); // error

但是构造函数是公开的; Java 中没有语言机制允许您限制用于调用构造函数的类型参数。

这个构造函数必须是公共的,因为它在泛型之前就存在了,所以删除它会违反向后兼容性。

【讨论】:

    【解决方案2】:

    您可以编写自己的函数,使其需要实现Comparable 才能编译:

    static <E extends Comparable> boolean addWithCheck(TreeSet<E> treeSet, E e) {
        return treeSet.add(e);
    }
    

    然后这样称呼它:

    TreeSet<Dummy> treeSet = new TreeSet<>();
    addWithCheck(treeSet, new Dummy());
    

    【讨论】:

      猜你喜欢
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-04
      • 1970-01-01
      • 2020-03-27
      • 2019-04-20
      相关资源
      最近更新 更多