gpt4 book ai didi

java - "Specializing"子类型的方法抛出检查异常?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:14:05 28 4
gpt4 key购买 nike

在我的 Java 项目中,我有以下类/接口(interface)层次结构:

public interface ProductSearcher {
Set<Product> search(String request);
}

public interface OnlineProductSearcher extends ProductSearcher {
}

public interface DatabaseProductSearcher extends ProductSearcher {
}

OnlineProductSearcher 在某个远程机器上搜索产品(例如,一个实现使用 HTTP),而 DatabaseProductSearcher 在我的本地机器中搜索产品(例如一个实现使用 JPA ).

事实证明,OnlineProductSearcher 有时可能会在搜索产品时出现问题,因为远程机器已关闭,正在限制我的请求速率,响应为 5xx、4xx 等等.

所以我想到了让我的 OnlineProductSearcher 实现在出现与远程机器相关的问题时抛出 RemoteMadeProblemsException
因为我想强制任何 OnlineProductSearcher 用户优雅地处理这些异常并且不会忘记这样做,所以我将 RemoteMadeProblemsException 设置为 checked exception,即RemoteMadeProblemsException 扩展异常

所以我继续并有了像这样重新定义 OnlineProductSearcher 的想法:

public interface OnlineProductSearcher extends ProductSearcher {
Set<Product> search(String request) throws RemoteMadeProblemsException;
}

但在 Java 中,不可能从子类型中的父类(super class)型重新声明/约束方法(Eclipse 告诉我“Exception RemoteMadeProblemsException is not compatible with throws clause in ProductSearcher.search(String)")

现在我看到了针对这种情况的两种解决方案:

  • 定义 ProductSearcher.search(String) 以抛出 RemoteMadeProblemsException
  • 或者使 RemoteMadeProblemsException 扩展 RuntimeException 并且没有 OnlineProductSearcher.search(String) 声明一个 throws条款。

我发现这两种解决方案都不合适:

  • 第一个解决方案,例如强制DatabaseProductSearcher.search任何 用户捕获/抛出一个没有意义的RemoteMadeProblemsException(毕竟它是一个本地数据库)。
  • 第二种解决方案为草率编程打开了大门。例如。有人使用 OnlineProductSearcher.search(String) 并忘记 try catch RemoteMadeProblemsException,让异常落空并波及。

对于这个“只有某些子类型可能会抛出异常”的问题,有什么更好的解决方案?

最佳答案

你遇到的问题是:

  ProductSearcher x = new OnlineProductSearcher();

这是完全合法的语法,现在如果有人调用 x.method(),Java 将无法知道该已检查的异常。

这就是为什么子类只能使实现更加具体。他们可以返回子类并接受父类(super class),但反之则不行。这是因为要求对父类(super class)方法的任何调用对子类方法也有效。

例如如果:

Number process(Integer i) {
}

是一个父类(super class),那么一个有效的子类是:

Integer process(Number i) {
}

因为在父类(super class)中对process的每次调用在子类中也是有效的。完全相同的参数适用于 throws 声明。通过让子类抛出检查异常,您就无法将其视为具有与父类(super class)中相同签名的方法。

您的困境的解决方案是定义一个更通用的异常 ProductSearcherException 并让 ProductSearcher 抛出该异常。

您的 OnlineSearcherException 然后是 ProductSearcherException 的子类并且您的 throw 声明变得合法。

你可以做的一件事是用三个类而不是一个来改进:

  • 您的基础 ProductSearcher 将方法声明为抛出异常
  • 不抛出异常的本地实现
  • 确实抛出异常(或更专业的异常)的远程实现。

这确实削弱了人们执行 ProductSearcher x = new LocalProductSearcher 然后使用更通用的类的能力(因为那时他们需要捕获异常)但对于使用 LocalProductSearcher 的任何人 自始至终他们都不需要 catch 。

请注意,即使在本地情况下,您可能会发现自己将来需要抛出异常,因此拥有它们并不可怕。

关于java - "Specializing"子类型的方法抛出检查异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23412632/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com