Try-Catch 块终止

Try-Catch block termination

我正在使用 try-catch 块来捕获当我 运行 堆栈上的某些方法时可能抛出的任何异常。我的 pop 方法代码如下所示:

public T pop()
{   
    T temp = null;
    try
    {
        temp = first.data;

    }
    catch(Exception e)
    {
         System.out.println("Invalid operation on an empty stack");

    }
    first = first.next;
    return temp;
}

当我 运行 程序异常被捕获时...我的终端产生这个: (菜单选择'd'是pop方式)

Please enter a menu choice: d

Invalid operation on an empty stack Exception in thread "main" java.lang.NullPointerException at MyStack.pop(MyStack.java:58) at StackTest.main(StackTest.java:52)

所以我认为我的异常被捕获了,因为它打印了 "Invalid operation...",但是当异常被抛出时我的程序也终止了。有帮助吗?

似乎有另一个异常被抛出, 你的 catch 块之后。 first 很可能为空。这会导致执行 catch 块(因为 first.data 是一个空指针异常),但它也会在

处导致另一个空指针异常
first = first.next;

因此你有一个未捕获的异常。你如何解决这个问题取决于你;它更像是一个设计决策,而不是正确性决策。

最简单且可能是正确的选择是在 try 块中执行 所有 修改,因此如果出现问题,您不会恢复可能无法运行的操作.

public T pop(){   
    T temp = null;
    try{
        temp = first.data;
        first = first.next;
    }
    catch(Exception e){
         System.out.println("Invalid operation on an empty stack");
    }
    return temp;
}

当然,try..catch 结构在这里并不合适。编写相同方法的更简洁的方法是:

public T pop(){   
    if(first == null) return null;

    //By virtue of reaching this point, first is necessarily non-null.
    T temp = first.data;
    first = first.next;
    return temp;
}

但如果目标是试验try..catch,请使用我的最佳答案。

根据您的输出,

first 显然是 null。现在,您正在捕获 temp = first.data 产生的 NullPointerException,而不是 first = first.next 产生的 NullPointerException(因为该赋值没有包含在 try 块中):

public T pop()
{   
    T temp = null;
    try
    {
        temp = first.data;  // <-- you catch the exception thrown here

    }
    catch(Exception e)
    {
         System.out.println("Invalid operation on an empty stack");

    }
    first = first.next;  // <-- but you don't catch the one thrown here
    return temp;
}

总的来说,抓住 NullPointerException 是一个 非常 的坏主意;事先明确检查 null

很有可能你的第一个是空的。

改用此代码

public T pop()
{   
    T temp = null;
    try 
    {
        if (first != null) 
        {
            temp = first.data;
            first = first.next;
        }
    }
    catch(Exception e)
    {
         System.out.println("Invalid operation on an empty stack");

    }
    return temp;
}

我们今天学到了非常宝贵的一课:不要无故抓Exception

这里的问题是 first 正在返回 null,所以我们将在尝试取消引用它时抛出该异常。

让我们换个角度来看。如果 first 为空,我们知道我们不能弹出任何东西,所以我们应该 抛出 异常。

public T pop() {
    if(first == null) {
        throw new EmptyStackException("Invalid operation on empty stack");
    }

    T value = first.data;
    first = first.next;
    return value;
}