问题
Is it better, less expensive or more readable to use a try/catch
block in Java instead of using multiple If
statements to check user input for example?
Example when parsing a Date
string, won't it be better to parse directly using a try/catch block instead of writing multiple statements looking for illegal characters.
In another example, say i want to read a file or stream, instead of using Scanner
, I just force the method and wait for an exception to occur.
Is that a healthy method of programming? Is it less expensive on the Virtual Machine?
UPDATE
Here is an example of what i meant when using DateFormat exception, sometimes it could be a real problem to catch an error, and when doing so, can you guarantee your complicated (usually unreadable) code is error prone?
回答1:
It's a bad practice to use Exceptions for a flow control.
Some quotes:
Because exceptions are designed for use under exceptional circumstances, few, if any, JVM implementations attempt to optimize their performance. It is generally expensive to create, throw, and catch an exception.
In the presence of an unrelated bug, the idiom can fail silently and mask the bug, greatly complicating the debugging process.
Update: As it's said (and I remember that I also found the same statement in Josh Bloch's blog) using exceptions for flow control is like using GOTOs for the same purpose. You can read interesting Dijkstra article about why GOTOs are bad.
回答2:
In general, exceptions are meant for... well, exceptional events. If
is meant for things that can occur during the normal course of events.
So typically, if you want to handle a case for which you don't have a good local solution, use an exception to propagate it upwards to someone who can deal with it better. This is significantly more costly than if-else
, that's one more reason not to abuse it. A third, IMHO equally important concern is readability: it is much more difficult to follow where the execution flow continues after a throw
, than to read a sequence of if
statements.
If you want to handle a case locally, most of the time it's better to use a simple if
.
回答3:
Exceptions are for exceptional cases. It's a bad idea to make program logic dependent on exceptions being thrown.
回答4:
It s more expensive to use Exception in place of If, because the compiler and the jvm will have more work and difficulty to optimize the control flow of these blocks, and in general exception are for exception.
回答5:
Exceptions are not good for performance, as they are meant for exceptional circumstances and thus there are tradeoff that make the non-exceptional case faster at the expense of making exceptions slower. That being said, it's impossible to say whether the difference is significant in a particular case without benchmarking that specific case.
But there is another, more important consideration: you should avoid duplication of logic. It's definitely not good to duplicate the date parsing logic to avoid exceptions. Unfortunately, Java does not have the TryParse()
methods found in the .NET framework, which allow you to use the framework's parsing logic for sanity testing without exceptions.
In such cases, I would favor using exceptions unless a profiler has identified them as performance bottleneck. But for simpler tests (nulls, end of file), I'd strongly avoid using exceptions as a substitute for if clauses.
回答6:
I would think it would be more expensive for the try catch to catch the exception plus the if statements would probably look cleaner.
回答7:
When an Exception is thrown, the message stack gets copied into the new Exception object in order to enable debugging and printStackTrace(). This is expensive.
If your in-thens get are getting excessive, consider flow-control patterns such as the Strategy, State, and Command patterns.
回答8:
Try catch is expensive only when exception is thrown, which I believe is because of stack trace creation. I run following benchmark to validate this:
public class TestTryCatchVsIfElseVsNoBlock
{
private static final int numberOfIteration = 1000000;
public static void main(String[] args)
{
//measureExIfElse
for (int i = 0; i < numberOfIteration; i++)
{
measureIfElse(null);
}
long start = System.nanoTime();
for (int i = 0; i < numberOfIteration; i++)
{
measureIfElse(null);
}
final long ExIfElse = (System.nanoTime() - start);
//measureExTryCatch
for (int i = 0; i < numberOfIteration; i++)
{
measureTryCatch(null);
}
start = System.nanoTime();
for (int i = 0; i < numberOfIteration; i++)
{
measureTryCatch(null);
}
final long ExTryCatch = (System.nanoTime() - start);
//measureIfElse
for (int i = 0; i < numberOfIteration; i++)
{
measureIfElse("Nitin");
}
start = System.nanoTime();
for (int i = 0; i < numberOfIteration; i++)
{
measureIfElse("Nitin");
}
final long IfElse = (System.nanoTime() - start);
//measureTryCatch
for (int i = 0; i < numberOfIteration; i++)
{
measureTryCatch("Nitin");
}
start = System.nanoTime();
for (int i = 0; i < numberOfIteration; i++)
{
measureTryCatch("Nitin");
}
final long TryCatch = (System.nanoTime() - start);
//WithoutAnyBlock
for (int i = 0; i < numberOfIteration; i++)
{
measureWithoutAnyBlock("Nitin");
}
start = System.nanoTime();
for (int i = 0; i < numberOfIteration; i++)
{
measureWithoutAnyBlock("Nitin");
}
final long WithoutAnyBlock = (System.nanoTime() - start);
System.err.println("ExIfElse: "+ ExIfElse/(float)numberOfIteration); // 3.563198
System.err.println("ExTryCatch: "+ ExTryCatch/(float)numberOfIteration); // 15.924681
System.err.println("IfElse: "+ IfElse/(float)numberOfIteration); // 1.683819
System.err.println("TryCatch: "+ TryCatch/(float)numberOfIteration); // 1.507893
System.err.println("WithoutAnyBlock: "+ WithoutAnyBlock/(float)numberOfIteration); // 1.750418
}
private static int i = 0;
private static void measureTryCatch(String s)
{
try
{
s.length();
}
catch (Exception e)
{
++i;
}
}
private static void measureWithoutAnyBlock(String s)
{
s.length();
}
private static void measureIfElse(String s)
{
if(s!=null)
{
s.length();
}
else
{
++i;
}
}
}
来源:https://stackoverflow.com/questions/2409179/is-it-better-to-use-try-catch-instead-of-multiple-if-statements