在 Java 中,如何强制异常“冒泡”?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24194626/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In Java, how to force an Exception to "bubble up"?
提问by Alexander Mills
I have a method that throws an Exception, which calls a method which throws an Exception, etc etc. So several methods that "throw Exception" are daisy-chained.
The first method that calls the submethod, puts that submethod in a try-catch block that catches any Exception
that gets thrown inside that call. IN THEORY. In practice, no Exception is being caught by that try-catch block. Is there a way to remedy that?
我有一个抛出异常的方法,它调用一个抛出异常的方法,等等。所以几个“抛出异常”的方法是菊花链的。调用子方法的第一个方法将该子方法放在一个 try-catch 块中,该块捕获Exception
在该调用中抛出的任何内容。理论上。实际上,该 try-catch 块不会捕获任何异常。有没有办法补救?
Here is the code:
这是代码:
try {
CSVSingleton.tryToReadBothFiles(FILE1_PATH, FILE2_PATH);
} catch (Exception e) { // THIS BLOCK NEVER GETS ENTERED BY THE PATH O EXECUTION
System.out.println("There was an exception reading from at least one of the files. Exiting.");
System.exit(0);
}
here is the method from the CSVSingleton class:
这是来自 CSVSingleton 类的方法:
public static void tryToReadBothFiles(String filePath1, String filePath2) throws Exception {
file1 = new CSVFileForDwellTime1(filePath1);
file2 = new CSVFileForDwellTime2(filePath2);
}
And here is code from the CSVFileForDwellTime1 class:
这是来自 CSVFileForDwellTime1 类的代码:
public CSVFileForDwellTime1(String filePath) throws Exception {
super(filePath);
}
and then here is the code that actually throws an original FileNotFoundException:
然后这里是实际抛出原始 FileNotFoundException 的代码:
public GenericCSVFile(String filePath) throws Exception{
this.filePath = filePath;
try {
fileReader = new FileReader(filePath);
csvReader = new CSVReader(
fileReader);
header = getActualHeaderNames();
} catch (FileNotFoundException e) {
System.out.println("Could not read file with name: " + filePath);
// e.printStackTrace();
}
}
My guess is that the FileNotFoundException in the last method is caught by the catch block and so doesn't "bubble up". But is there a way to force it to bubble up?
我的猜测是最后一个方法中的 FileNotFoundException 被 catch 块捕获,因此不会“冒泡”。但是有没有办法强迫它冒泡?
采纳答案by RossBille
Immediate answer:
立即答复:
Your thought is exactly right,
你的想法完全正确
try {
fileReader = new FileReader(filePath);
csvReader = new CSVReader(
fileReader);
header = getActualHeaderNames();
} catch (FileNotFoundException e) {
System.out.println("Could not read file with name: " + filePath);
// e.printStackTrace();
}
This suppresses the exception
Either remove the try-catch
block (desired unless you can actually do something with the exception)or re-throw it within the catch
block.
这会抑制异常要么删除try-catch
块(除非您实际上可以对异常执行某些操作,否则需要)或在catch
块中重新抛出它。
Explanation
解释
Generally with checked
exceptions like this you have 2 options
通常,checked
除了像这样的例外,您有 2 个选择
- Catch the exception and do something to remedy the exception
- Throw the exception to the caller
- 捕获异常并做一些事情来补救异常
- 向调用者抛出异常
What you have done here falls into the 1st category except that you have not done anything useful in the catch
block (printing to console is rarely useful in this case because the exception message itself normally has enough information to see what has gone wrong)
你在这里所做的属于第一类,除了你没有在catch
块中做任何有用的事情(在这种情况下打印到控制台很少有用,因为异常消息本身通常有足够的信息来查看出了什么问题)
The 2nd category is achieved either by not using a try-catch
block and thus adding throws FileNotFoundException
to the method signature. Alternatively explicitly throw
the exception that you caught using:
第二类是通过不使用try-catch
块并因此添加throws FileNotFoundException
到方法签名来实现的。或者throw
,您使用以下方法明确捕获的异常:
catch(FileNotFoundException e)
{
//do something
throw e;
}
however in this case if do something
isn't worthwhile you have unnecessarily caught something just to throw it on.
但是在这种情况下,如果do something
不值得,你不必要地抓住了一些东西只是为了扔掉它。
You can think of it like this:
你可以这样想:
Alice throws a ball to Charlie
Bob intercepts the ball
Bob then looks at the ball and then throws it to Charlie
Bonus Points
奖励积分
When you know the exception that could occur make sure to actually catch
or throw
that exception and not a parent of that exception.
Take the following method signatures for example:
当您知道可能发生的异常时,请确保实际catch
或throw
该异常而不是该异常的父级。以下面的方法签名为例:
public String method1() throws Exception
public String method2() throws FileNotFoundException
Here method2
clearly tells the caller what could happen and can help then figure out why the exception is being called (without having to read through the code or experience the error).
这里method2
清楚地告诉调用者可能发生什么,然后可以帮助找出调用异常的原因(无需通读代码或遇到错误)。
Secondly other exceptions can occur and you are potentially catching the wrong exception, take the following example:
其次,可能会发生其他异常,您可能会捕获错误的异常,请看以下示例:
try{
fileReader = new FileReader(filePath); //could potentially throw FileNotFoundException
fileReader = null; //woops
csvReader = new CSVReader(fileReader); //throws NullPointerException but the compiler will not know this
//....other stuff....//
}
catch(Exception e){
// the compiler told me that a FileNotFoundException can occur so i assume that is the reason the catch has executed
System.err.println("You have entered an invalid filename");
//doing anything here that would fix a FileNotFoundException is pointless because that is not the exception that occured
}
回答by M Anouti
Technically you just need to add throw e
right after System.out.println("Could not read file with name: " + filePath);
and the exception will propagate up to the first method.
从技术上讲,你只需要添加throw e
之后System.out.println("Could not read file with name: " + filePath);
,异常将传播到第一个方法。
However, this would not be a clean way to handle the exception, because in this case all you'd be doing is printing an error message at the cost of changing the location of the original FileNotFoundException
. Ideally, when you need to inspect an exception stacktrace, you expect a line of code throwing an exception to be the actualline that really caused the exception.
但是,这不是处理异常的干净方法,因为在这种情况下,您所做的只是以更改原始FileNotFoundException
. 理想情况下,当您需要检查异常堆栈跟踪时,您希望抛出异常的代码行是真正导致异常的实际行。
The throws Exception
in the method declaration should be considered part of the contract of the method, i.e. it describes a possible behavior of the method. You should always ask yourself: Does it make sense for a FileNotFoundException
to be specified as a possible exceptional behavior for the method/constructor I'm writing? In other words, do I want to make the caller of my method aware of this exception and leave it to the caller to deal with it? If the answer is yes (and in this case I would say it makes sense), then avoid wrapping the code in a try-catch
block. If no, then your catch
block should be responsible for dealing with the exception itself. In this specific example IMO there is not much you can do in the catch
statement, so just remove the try-catch
.
该throws Exception
方法声明应被视为法的合同的一部分,也就是说,它描述了该方法的一个可能的行为。您应该始终问自己:将 aFileNotFoundException
指定为我正在编写的方法/构造函数的可能异常行为是否有意义?换句话说,我是否想让我的方法的调用者知道这个异常并将它留给调用者来处理?如果答案是肯定的(在这种情况下我会说这是有道理的),那么避免将代码包装在一个try-catch
块中。如果不是,那么您的catch
块应该负责处理异常本身。在这个特定的例子中,IMO 在catch
语句中没有什么可以做的,所以只需删除try-catch
.
As mentioned by others, you should declare the most specificexception in the method signature (throws FileNotFoundException
instead of throws Exception
).
正如其他人所提到的,您应该在方法签名中声明最具体的异常(throws FileNotFoundException
而不是throws Exception
)。
回答by NESPowerGlove
You can rethrow the exception once you catch it, for callees further up the stack to handle. You can change what exception it is too if a new type of exception makes more sense at a higher level.
您可以在捕获异常后重新抛出异常,以便在堆栈上进一步处理的被调用者进行处理。如果新类型的异常在更高级别更有意义,您也可以更改它是什么异常。
catch (SomeSpecificException e)
{
some code here
throw new AMoreBroadException("I really need the callee to handle this too");
}
回答by user2864740
Use a throw
in the catch clause.
throw
在 catch 子句中使用 a 。
} catch (FileNotFoundException e) {
System.out.println("Could not read file with name: " + filePath);
// Continue up, Mr. Exception!
throw e;
}
Alternatively, wrap the exception as appropriate (since an IOException is checked this handy here) - this is called a Chained Exception. Then, depending on what is thrown, the throws Exception
can be removed from the method signature.
或者,适当地包装异常(因为在这里检查 IOException 很方便) - 这称为Chained Exception。然后,根据抛出的内容,throws Exception
可以从方法签名中删除 。
throw new RuntimeException("Could not read file: " + filePath, e);
回答by Zyl
If you don't want to catch it, then don't. Alternatively, you can just throw it again with a throw
-statement. You can also throw a new Exception of any class you like. You should only catch an Exception at a level where you can react to it properly. As you found out, catching it at that low level is not helpful, so do not catch it there.
如果你不想抓住它,那就不要。或者,您可以使用 -throw
语句再次抛出它。您还可以抛出您喜欢的任何类的新异常。您应该只在可以对其做出正确反应的级别上捕获异常。正如您所发现的,在那个低级别捕获它没有帮助,所以不要在那里捕获它。