0

这里说不可能从错误中恢复。我不确定这是什么意思,因为我可以像异常一样捕获错误。例如:

public static void main(String args[]) {
    while (true) {
        try {
            throw new StackOverflowError("stackoverflow");
        } catch (Throwable throwable) {
            //do something
        }
        //program recover and continue to execute
    }
}

上述程序正常执行,似乎可以从错误中恢复。任何人都可以帮忙吗?

更新:

stackoverflow的例子有点令人费解,只有白痴想从stackoverflow中恢复。这是关于 OutOfMemory 的另一个示例:

public class Main {
    public static Map<Long, Object> cache = null;
    public static void main(String args[]){
        while(true){
            try {
                if(cache == null) {
                    cache = new HashMap<>();
                }
                for (long i = 0; i < Long.MAX_VALUE; ++i) {
                    cache.put(i, i);
                }
            }catch(OutOfMemoryError error) {
                cache.clear();//delete some unused entry or clear all.
                cache = null;
                System.gc();
                System.out.println("release memory");
            }
        }
    }
} 

这是一个简单的HashMap缓存,使用 执行代码java -Xmx1m Main,很快就会看到OutOfMemoryError,然后手动释放内存,程序会继续执行。插入-> OutOfMemoryError -> 释放-> 插入...看到了吗?程序已从 OutOfMemoryError 中恢复。不是吗?而且我认为这很有意义。那么,为什么有人仍然说程序无法从 OutOfMemoryError 中恢复。

4

3 回答 3

3

显然,仅仅“捕获”异常的能力并不意味着您将(总是......)能够“从中恢复 ......

......即:   “全力以赴,毫发无损,就好像'这样不方便的事件'从来没有发生过一样。”

我认为原作者的要点或多或少是:即使泰坦尼克号上的可怜灵魂可能已经“抓住”了他们的船正在沉没的事实,他们也无能为力“恢复”这艘船安然无恙地航行到纽约。

---编辑: “现在,让我再补充一个想法!” (正如其他回答者在这里所做的那样。)有时,在有意被 catch 块包围的某些代码块中 故意“抛出”错误异常。

也许错误(它本身是“一个对象”)是捕手可以识别的特定用户定义类型。(他可以“重新扔”任何他不认识的东西,或者干脆拒绝抓住它。)这可能是一种非常优雅和有效的方式来处理“规则的例外”。(由此得名...)

每当一个代码块遇到“在蓝月亮中只发生一次,但它确实发生过”的情况时,它可以将异常抛向空中,因为它知道最近的捕手捕获它。反过来,这个接球手可以识别刚刚落入棒球手套的东西,并做出相应的反应。那里可以有任意数量的“捕手”,寻找不同的东西。

这种策略不是“错误”,而是程序内有意的替代控制流。

于 2016-07-15T03:40:04.613 回答
1

考虑下面的代码,它实际上抛出了一个StackOverflowError

public class Code
{
    public static void main(String[] args)
    {
        try
        {
            f();
        }
        catch (Throwable t)
        {               
            System.out.println("OK I'm recovered, let me try that again");

            try
            {
                f();
            }
            catch (Throwable t2)
            {
                System.out.println("What's going on here??");

                // let me try one more time.. 
                try
                {
                   f();
                }
                catch (Throwable t3)
                {
                     System.out.println("Why can't I really recover");
                }
            }
        }

    }

    // Bad recursion...
    private static void f()
    {
        f();
    }
}

知道您的代码存在这样的问题,您真的想继续执行吗?如果您需要f()再次拨打电话线下的某个地方怎么办?如果方法不断给出 StackOverflowError,您是否希望在生产中尝试继续这样的代码?

于 2016-07-15T03:28:11.410 回答
0

你只是Throwable在它到达错误的地步之前抓住了这里。Throwable错误和异常的超类。因此,Throwable 无法与错误本身相提并论,更不用说 StackOverflowError,而且您的程序无法从错误中恢复。

一个例外有点像轻罪指控。发生在你身上,或者更确切地说,你的程序,这不是一件了不起的事情,但它绝对不会让你在监狱里呆很长时间。然而,错误是危险的——继续这个类比是重罪。Java 被认为比 C 更安全,因为它会告诉你什么时候做不安全的事情。另一方面,例如,C 将允许您访问超出数组范围的数据,并且您会遇到很难以这种方式调试的可怕错误。

与犯罪的类比在那之后就结束了。如果您在链接到的页面上向下滚动一点,它会继续描述异常和错误不同的原因,即“错误是由应用程序运行的环境引起的”,因此,因为您的应用程序只负责自己,而不是实际环境,所以它不能自行从错误中恢复。

该页面还给出了 OutOfMemoryError 的示例。虽然作为程序员,您可以提前计划通过使代码尽可能高效来尝试防止 OutOfMemoryError,但如果代码运行在具有以下功能的机器上,您将无法防止此类错误: 1 个字节的 RAM。错误无法被捕获,因为它们(大部分)不在应用程序本身的控制之下。这取决于程序员,例如在Michael Markidis 的示例中,不要导致错误并避免任何Bad recursion会导致程序崩溃的导致错误的编程技术(例如使用“”)。

于 2016-07-15T03:37:55.067 回答