Java:为什么我不能在Comparator中抛出exception?

直接的答案是因为Comparator.compare的接口被指定为不会抛出exception。 但那是为什么呢?

或者说它不同:我的Comparator必须依赖于可以抛出exception的函数。 从理论上讲,这不应该发生。 但如果它发生了,我希望它突破我使用该Comparator的整个函数(在Collections.sort )。 即我希望它只是表现为发生了未处理的exception。

看起来这是不可能以一种明显的自然方式(因为如果接口说它不能抛出exception,它就不能)。

我该如何解决这个问题? 有一个丑陋的尝试/捕获并打印出exception并希望我认识到它? 这似乎是一种非常丑陋的方式。

在这种情况下,我会重新抛出AssertionError因为您认为无法引发exception。 不要忘记使用initCause()方法传播信息( AssertionError没有接受Throwable的构造函数)

您始终可以抛出RuntimeException或从中派生的RuntimeException ,甚至可以从未明确声明自己抛出exception的方法抛出。

这是Comparator.compare方法的合同。 如果你想使用它,你应该遵循规则不要从中抛出已检查的exception:)同时,你可以抛出未经检查的exception( RuntimeException或它的子类),这不会破坏合同。

这是因为您没有使用Lombok的@SneakyThrows注释注释您的方法。
请访问http://projectlombok.org/features/SneakyThrows.html查看

龙目岛主页上的演示和幻灯片也值得一看http://projectlombok.org/

您在问题标题和问题正文中提出了不同的问题。

您不清楚为什么compare()方法使用的exception函数会抛出exception。 这要么是因为集合中存在某些不可比较的对象(如NaN数字值),要么就是因为某些对象无法相互比较。

为什么我不能在比较器中抛出exception?

我猜Comparator.compare()不是为了抛出一个已检查的exception,因为:

  1. 假设您希望比较/排序的任何项目始终具有可比性。

  2. 如果Comparator.compare()可以抛出某种预期的(即已检查的)exception,那么我可以设想一些不期望的情况:

    一个。 排序可能会中止,因为那里存在某种不可比较的对象 – 可能的响应是删除不可比较的对象并再次尝试排序

    湾 对同一对象集合的不同排序的多种排序有时会因exception而中止,有时会取决于是否在排序期间出现了一对无法比较的对象进行比较

这当然只是我猜想的。

我该如何解决这个问题?

我将假设Comparator.compare()使用的exception可能函数抛出exception的原因是因为集合中存在一个无法Comparator.compare()的对象(如NaN数字值)。 选项包括:

  1. 在删除了无法比较的对象的情况下对列表的副本进行排序。

  2. 抛出未经检查的(运行时)exception以中止排序。 不知道除了#1以外你会做什么。

  3. 按照NaN方法进行操作,使这些对象在开始或结束时出现。

    NaN值通常与其他值无法比较,但在排序期间,比较器定义其自己的总排序,以便NaN值最终在排序集合的末尾。

    http://download.oracle.com/javase/1.4.2/docs/api/java/util/Arrays.html#sort(双%5B%5D)

    …要允许排序继续,…此方法使用Double.compareTo(java.lang.Double)强加的总顺序。

    …此排序与

    为此,请对Comparator.compare()编码,使得任何无法比较的对象始终比任何可比对象都要大,并且它总是与任何其他无法比较的对象进行比较。

有两种方法可以解决这个问题:

  1. 捕获exception并将其抛入java.lang.RuntimeException()
  2. 捕获exception并使用Log4J或SLF4J(或您认为合适的任何记录器工厂)记录它。

比较器比较方法的合同不会引发exception。

您可以通过使用许多技巧重新抛出已检查的exception并避免编译错误。 最简单的是;

 try { // something } catch (Exception e) { Thread.currentThread().stop(e); } 

但是,由于编译器不知道你已经这样做了。 如果你不小心,你可以把它和自己混淆。 闭包的目标之一是正确处理比较器等事件中的已检查exception(而其他人则希望它们消失)