控制台显示异常消息但仍然是错误的异常类型——为什么?

Console displays exception message but is still wrong exception type -- Why?

我正在尝试创建一个名为 bag 的抽象数据类型,它基本上使用方法 add(int x) 接收整数,并使用方法 remove() 删除任意整数。

然后,我尝试为 remove() 方法创建一个自定义异常,因为当包中已经没有物品时,有可能完成移除。因此,我创建了一个异常 class 这样的:

public class EmptyBagException extends Exception {
    public EmptyBagException(String message) {
        super(message);
    }
}

然后像这样继续使用这个自定义异常:

public int remove() {

    try {
        this.realRemoval();
    } catch (EmptyBagException e){
        System.out.println(e.getMessage());
    }

    return -1;
}

public int realRemoval() throws EmptyBagException {

    if (counter == 0) {
        throw new EmptyBagException("There are no items in the bag!");
    } else {
        ...
    }
}

然后,我尝试通过这样做来测试异常:

@Rule
public ExpectedException thrown = ExpectedException.none(); 

@Test
public void testThree() {

    IBag myBag = new BasicBag();
    myBag.remove();
    thrown.expect(EmptyBagException.class);
    thrown.expectMessage("There are no items in the bag!");

}

不幸的是,这次测试失败了,我收到消息:

java.lang.AssertionError: Expected test to throw (an instance of sg.com.practice.adt.EmptyBagException and exception with message a string containing "There are no items in the bag!")

我不确定为什么会这样...特别是因为我预期的错误消息确实正确地打印到控制台。在此先感谢您的帮助!

这是因为你实际上并没有抛出异常 remove():

public int remove() {

    try {
        this.realRemoval();
    } catch (EmptyBagException e){
        System.out.println(e.getMessage());
    }

    return -1;
}

在这种情况下,来自 realRemoval() 的异常被您的 try...catch 块捕获并处理。异常由 realRemoval() 抛出,然后被您的处理程序捕获,消息被打印出来,仅此而已:异常没有被重新抛出,-1 被 returned 代替。

如果你想让它重新抛出异常,你必须这样做:

public int remove() throws EmptyBagException { // <-- declare throws

    try {
        this.realRemoval();
    } catch (EmptyBagException e){
        System.out.println(e.getMessage());
        throw e; // <-- rethrow
    }

    return -1;

}

或者干脆去掉你的输出信息,让它自然发生:

public int remove() throws EmptyBagException { // <-- declare throws

    this.realRemoval(); // <-- may throw

    return -1;

}

另请注意,在测试函数中调用 remove() 之前,您需要设置 thrown ,就好像 remove() 抛出, 然后测试函数将抛出并且实际上不会超过那个点来设置 thrown.

顺便问一下,你不是说 return realRemoval() 的值而不是 -1 吗?