Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在';中创建可恢复的错误接口是否比处理恢复更有效;捕捉';_Java_Exception_Try Catch - Fatal编程技术网

Java 在';中创建可恢复的错误接口是否比处理恢复更有效;捕捉';

Java 在';中创建可恢复的错误接口是否比处理恢复更有效;捕捉';,java,exception,try-catch,Java,Exception,Try Catch,注意这个问题以观点为基础,所以我用更实际的方法重新提问 因此,正如标题所说,我不确定是应该尝试实现可恢复的错误类,还是继续尝试在catch块中进行恢复 要演示的一些psuedo代码: // more or less what I have now postToServer(data) { try { socket.write(data) } //Interrupted being a custom exception catch(Interrupt

注意这个问题以观点为基础,所以我用更实际的方法重新提问

因此,正如标题所说,我不确定是应该尝试实现可恢复的错误类,还是继续尝试在
catch
块中进行恢复

要演示的一些psuedo代码:

// more or less what I have now
postToServer(data) {
    try {
        socket.write(data)
    }
    //Interrupted being a custom exception
    catch(Interrupted ex) {
        //happened twice is a common static method on all custom exceptions that returns a boolean indicating if the last thrown error is the same as this one
        if(Interrupted.happenedTwice(ex)) throw ex;
        else postToServer(data);
    } 
    //another custom exception indicating that the network is unreachable
    catch(NetworkDrop ex) {
        if(!NetworkDrop.happenedTwice(ex) && !reconnectToServer()) throw ex;
        else postToServer(data);
    }
}
//What I would like to implement
interface Recoverable {
    public void recover(Runnable) throws Exception;
}
class NetworkDrop extends Exception implements Recoverable {
    ...
    public void recover(Runnable resume) {
        if(!NetworkDrop.happenedTwice(this) && reconnectToServer()) resume.run();
        else throw this;
    } 
}
class Interrupted extends Exception implements Recoverable {
    ...
    public void recover(Runnable resume) {
        if(!Interrupted.happenedTwice(this)) resume.run();
        else throw this;
    }     
}
postToServer(data) throws Exception {
    try {
        socket.write(data)
    }
    catch(Recoverable ex) {
        ex.recover(() -> postToServer(data));
    }
}

作为示例,我希望所有的恢复代码都在异常中(减少重复代码,正如现在所说的,5种不同的方法可以调用
recover
,而不是运行相同的恢复代码)。这将允许我捕获可以恢复的异常,但仍然抛出不可恢复的异常,或者在无法恢复时抛出异常

但我认为这有一个问题:

当从恢复中调用的中间
Runnable
不返回数据时,如何在预期返回数据的方法中恢复? 假设我正在从服务器读取而不是写入,并获得一个可恢复的异常(如NetworkDrop)并成功恢复。由于执行是通过recover方法上的Runnable恢复的,并且Runnable不返回任何内容,那么调用read的函数如何从Runnable中获取数据呢

那么,这个系统会比多个
捕获
更有效吗?或者说,仅仅捕获可恢复异常所带来的可读性和简单性是一把双刃剑


如果折衷有利于可恢复类,我将如何解决从恢复的异常中获取返回值的问题?

异常意味着在调用堆栈上进行故障通信。抛出异常尤其支持这样一种特性,即在某个嵌套调用失败后,调用方通常不想继续,而是在堆栈的更上层发出失败信号

因此,在接收到异常后,调用方跳过其方法体的其余部分,并向其调用方发出失败信号,这在所有调用堆栈中都会发生,直到您找到具有适当的
catch
块的位置

瑕疵 您的
Recoverable
异常将破坏该系统。如果我理解正确,恢复是一个双重过程:异常包含如何重新建立连接的代码,可运行由catch块提供,负责修复由于异常而跳过的代码行

但是由于跳过的代码将来自多个嵌套的调用层,我认为您无法可靠地提供有效的恢复代码

当然,如果您准备在每个软件层上用try/catch来包围每一行业务代码,这会变得更容易,但这与异常处理的精神相矛盾

为了确立您的概念,您无论如何都需要确定可能发生可恢复故障的所有位置—您必须抛出
可恢复的
异常,通常会包装一些原始异常。这是另一种方法的关键

暗示 我建议使用不同的方法:

在所有抛出可恢复异常的地方,您都知道可以从故障中恢复。因此,我将在那里实现这些知识,而不是让方法失败,而是立即应用恢复策略,这样您就可以成功地返回


如果您担心恢复失败会浪费太多的尝试,请查看“断路器”模式。

这听起来过于复杂,通常比try-catch更糟糕。请参考您的示例“我可以使用Runnable调用recover,它将重试上一个操作,这将检查文件访问,创建父目录”,然后我的问题是-如果您认为权限可能错误,或者目录不存在,为什么在尝试访问文件之前不确定它们是否存在?例外情况适用于例外情况。“在访问文件之前不检查文件是否存在”也不例外。@Michael我理解你的意思。这可能是个坏例子,但很容易想到;)我认为这对于嵌入式环境中的线程任务非常有用,因此我将以它为例,例如发送SPI设备数据,设备处于坏状态,因此通过强制设备重新启动来恢复,并在设备重新启动时调用runnable。如果这是个坏主意,回答是这样的,为什么会这样,以便其他人可以引用它,我会接受它。我认为我们需要看到实际的代码,才能做出任何明智的判断。我明白你的意思,我的直觉是,这不是一个好方法,但要准确地解释为什么我需要用一些具体的例子来演示。如果你寻找更好的错误处理方法的想法和灵感,我个人的建议是阅读有关将你的应用程序建模为管道/操作图的框架(参与者模型、反应流)或函数编程。例如,您可以阅读(我认为重试运算符特别接近您的初始问题)。感谢您提供了一篇内容丰富的帖子!这篇文章的信息量和帮助性要比其他人只是询问您为什么要这样做,并说他们不理解,所以不要这样做。我的印象是,异常是当今最不被理解的软件功能。即使是著名的教程通常也只涉及异常的机制,而不是异常的灵魂。因此我试着分享我的理解,希望它能被证明是有用的。非常感谢,好先生。我在这里更真实地问了我的问题:你能检查一下并提供反馈吗?只是为了第二个意见哈哈