当前位置: 首页 > 知识库问答 >
问题:

是否可以声明某个供应商需要抛出异常?

饶承宣
2023-03-14

所以我正在尝试重构以下代码:

/**
 * Returns the duration from the config file.
 * 
 * @return  The duration.
 */
private Duration durationFromConfig() {
    try {
        return durationFromConfigInner();
    } catch (IOException ex) {
        throw new IllegalStateException("The config file (\"" + configFile + "\") has not been found.");
    }
}

/**
 * Returns the duration from the config file.
 * 
 * Searches the log file for the first line indicating the config entry for this instance.
 * 
 * @return  The duration.
 * @throws FileNotFoundException If the config file has not been found.
 */
private Duration durationFromConfigInner() throws IOException {
    String entryKey = subClass.getSimpleName();
    configLastModified = Files.getLastModifiedTime(configFile);
    String entryValue = ConfigFileUtils.readFileEntry(configFile, entryKey);
    return Duration.of(entryValue);
}

我想出了下面的开头:

private <T> T getFromConfig(final Supplier<T> supplier) {
    try {
        return supplier.get();
    } catch (IOException ex) {
        throw new IllegalStateException("The config file (\"" + configFile + "\") has not been found.");
    }
}

但是,它不编译(显然),因为supplier不能抛出IOException。有什么方法可以将它添加到GetFromConfig的方法声明中吗?

还是只有这样才能做到?

@FunctionalInterface
public interface SupplierWithIO<T> extends Supplier<T> {
    @Override
    @Deprecated
    default public T get() {
        throw new UnsupportedOperationException();
    }

    public T getWithIO() throws IOException;
}

更新后,我才意识到supplier接口非常简单,因为它只有get()方法。我扩展supplier的最初原因是优先于基本功能,例如默认方法。

共有1个答案

容飞掣
2023-03-14

在lambda邮件列表中对此进行了详细讨论。正如您所看到的,Brian Goetz在那里建议,另一种选择是编写您自己的组合子:

或者您可以编写自己的简单组合子:

static<T> Block<T> exceptionWrappingBlock(Block<T> b) {
     return e -> {
         try { b.accept(e); }
         catch (Exception e) { throw new RTE(e); }
     };
}

你可以只写一次,只需花更少的时间来写你最初的电子邮件。对于您使用的每种SAM,同样地也要使用一次。

我宁愿我们把它看成是“满99%的玻璃杯”,而不是另一个选择。并不是所有的问题都需要新的语言特性作为解决方案。(更不用说新的语言特性总是会引起新的问题。)

在那个时代,消费者接口被称为块。

EG讨论了对此问题的额外语言和库支持,最后认为这是一个糟糕的成本/收益权衡。

基于库的解决方案导致SAM类型的2倍爆炸(例外与不例外),这些爆炸与现有的基元专门化组合爆炸交互不良。

现有的基于语言的解决方案是复杂度/价值权衡的输家。尽管有一些替代的解决方案,我们将继续探索--尽管显然不是8的,也可能不是9的。

 类似资料:
  • 问题内容: 考虑以下代码: 无需添加方法签名即可编译该代码。(它与同样表现到位,太)。 我理解为什么 可以 安全地运行它,因为实际上不能将其引发在块中,因此不能引发已检查的异常。我有兴趣知道在何处指定此行为。 并非永远都不会达到目标:以下代码也会编译: 但是,如果抛出一个检查的异常,它不会像我期望的那样编译: 在JLS Sec 11.2.2中 ,它说: 一,其抛出的表达式语句(§14.18)具有静

  • 根据我读到的其他问题(为什么重写方法不能抛出比重写方法更广的异常?以及Java方法抛出异常) 我知道子类中的重写方法必须抛出在重写方法中抛出的异常的相同或一个子类。 Java方法总是至少抛出一个类型为exception的异常吗? ...换句话说,编译器添加抛出异常 因此类X将如下所示 我想澄清的是,对于始终添加默认异常处理程序异常这一事实,我没有搞错。 相关问题: IOException与Runt

  • 主要内容:throws 声明异常,throw 拋出异常Java 中的异常处理除了捕获异常和处理异常之外,还包括声明异常和拋出异常。实现声明和抛出异常的关键字非常相似,它们是 throws 和 throw。 可以通过 throws 关键字在方法上声明该方法要拋出的异常,然后 在方法内部通过 throw 拋出异常对象。本节详细介绍在 Java 中如何声明异常和拋出异常。 throws 声明异常 当一个方法产生一个它不处理的异常时,那么就需要在该方法的头部

  • 在Java中,检查的异常和未检查的异常都可以显式抛出,即通过语句(在字节码中转换为指令)。此外,像和这样的未经检查的异常可以在没有任何显式的语句的情况下触发: 所以我的问题是,是否有任何方法可以隐式地触发一个检查异常,比如,即不使用任何语句?

  • 我目前正在讨论消费者和供应商的话题,有以下问题。供应商的返回值是否可以递增? 下面是一个做作的例子:我有一个简单的class Person,id和name。例如,如果出于测试目的我需要10个人,我想用顺序ID轻松地生成他们。从供应商处获取id时,如何增加id? 这样做是我的想法: 或者构造供应商不打算用于这种用例?

  • 问题内容: 如果我有抛出未检查的异常的方法,例如: 明确声明该方法引发异常有什么好处,即 与(或除了)描述javadoc中的行为相反: 我之所以声称拥有无效的原因是: 没有提供有关在什么情况下会引发异常的信息,只是提供了 可能 引发异常的信息; 因为它是未经检查的异常,所以我不必在调用代码中处理该异常。我只会真正知道,如果我去看看的实现,可能会抛出该错误; 的主体可能会调用引发其他类型的未经检查的