可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am wondering how in practice other SOers tend to deal with and/or prevent exceptions.
In what situations do you prevent exceptions, and how?
In what situations do you catch exceptions?
I usually prevent 'NullPointerExceptions' (and other similar ones) by, well, essentially saying if(foo!=null) {...}
I find that in most situations this is less bulky than everything involved in using a try-catch block.
I use try-catch blocks when the potential exceptions are more complex, or more numerous.
回答1:
In my opinion, it only makes sense to prevent a NullPointerException (for example) when a reference being null (again, for example) actually represents a valid program state. If it does not, you should not prevent it from happening, because in that case you want the program to die hard.
In Java in particular, certain exceptions descending from RuntimeException (such as IllegalArgumentException) are really meant to signal programming errors, conditions that should not happen if your program is correct. I try to follow this. If I am writing a method that places restrictions on its arguments, I will not try to avoid throwing an exception. I will throw one aggressively.
回答2:
If you can prevent exceptions, then it's better programming practice to do so. For example, any NullPointerException usually indicates a programming error, IMO. (Which is one reason it's a RuntimeException.)
Exceptions are more useful when you expect to be able to detect a failure condition in one layer of code, but you don't want to handle the failure condition there but instead at a somewhat higher level of code. That is, you intend to throw the Exception more than one frame up the stack -- or all of the way up the stack. Exceptions are also useful when you do not expect the program to be able to meaningfully handle the problem.
回答3:
There are three kinds of exceptions.
Runtime exceptions are always preventable. You just have to program correctly.
Checked exceptions should be transformed to the right level of abstraction if possible ( not throw a SQLException to the user if he doesn't know/care about SQL exceptions ) or handled at the higher level ( that is, let them pop up ) and display/log proper message.
Errors should not be handled at all.
See the link for more details on how to prevent RuntimeExceptions
回答4:
Catch exceptions where you know how to deal with them.
You shouldn't check for (foo!=null) everywhere, check where foo is first used only. After that just use foo without checking. If foo suddenly becomes null after you've made sure it isn't null, you have big problems. An exception is appropriate then.
try {
foo();
}
catch (FooException e) {
}
is a bad code smell, and should be avoided
回答5:
I will check the input parameters at the beginning of a method and throw an IllegalArgumentException if they are outside what should be passed to the method. The idea being that it's a programming error and it should be fixed. Better now than when it's out in the field. If in the middle of a method I get an unexpected condition (null in a list, etc) I will log a fatal message and do a System.exit(2). Again this forces you to fix an issue vs. just logging it and moving on.
回答6:
Avoid the ones you can (NullPointerExceptions, NullReferenceExceptions, etc.).
Catch the ones that are a little trickier to catch (Sql Errors...where they may be out of your control but you need to gracefully clean up after them).
回答7:
I want all of my exceptions to travel upwards unless they are minor then I will swallow them (ex: prevent a claim entry dieing because an email notification function generated a NPE... I would like to swallow that NPE and keep trucking on as long as the real meat of the program throws no exceptions).
I use this method to force most of Java's unrecoverable yet checked exceptions:
http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html
回答8:
In general, exceptions should be something exceptional, e.g. unforeseeable or due to programming errors.
The problem is, there are a couple of dubious design descisions in the Java class library so you end up with idioms like:
class Foo {
static BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
int getInt() throws IOException {
int r=0;
for(;;) {
String s=in.readLine();
try {
r=Integer.parseInt(s);
break;
}
catch(NumberFormatException e) {
System.out.println("Please enter a valid integer.");
}
}
return r;
}
}
Clearly that code isn't perfect (will throw a NullPointerException on EOF) but it demonstrates the issue of using exceptions for things that aren't actually exceptional.
回答9:
I use the following class throughout my code to validate and abort processing:
@Getter
@Setter
public class Abort<T> {
private boolean abortProcessing;
private T response;
}
This way you can validate or catch exceptions immediately, log them and return the abort object.
回答10:
In general, if it is reasonable to do so, you should try to prevent the exception from occurring in the first place. Quite frequently, it's not reasonable or possibly flat-out impossible (especially when io in concerned), but that's what try/catch are for. In particular, this means that you should always check your pointers and your array indexes to prevent the NullPointerException and ArrayIndexOutOfBoundsException. Unless, of course, there is nothing you can do about it and would have to rethrow it anyway.
回答11:
you should catch all exceptions you can. NullPointerException
s can always be prevented with a simple if
statement. some other exceptions, like most IOException
s, are hard to be prevented. and besides the boilerplate needed to use a try/catch block, if your class throws an exception, an object of that exception will be created and it must be garbage collected... so by not throwing exceptions, you also make your VM healthier.
回答12:
In general, I use exceptions when the exception should cause a process to abort. When I'm going to do something about the problem and recover in some way, I try to prevent the exception from ever happening.
Like, if a parameter is passed in to a subroutine and I reasonably expect that it might be null, I'll check it for null. In real life, for example, a null String often is equivalent to a zero-length String, in which I'll just write < if (s==null) s=""; >.
But if a null String means that something has gone badly wrong and we should just quit the whole process and display a "Panic -- Abort -- World ending soon" type of message to the user, then an exception is very handy. You can throw the exception way down deep inside many layers of subroutines, and just catch it at the top, display the message, and you're done.
I often create my own exceptions for such conditions. Many of my programs are sprinkled with code like < throw new BadInputException("Customer number not found") > to just get me out, display a message, and quit. This really saves on deep nesting of IFs and constant checking of return values from subroutines.
回答13:
I prevent whenever possible, but I catch things the user has impact on, for example when they enter the wrong type of data. In Java, I have a class that I wrote which extends Scanner and keeps asking for proper input until it is valid. (From CLI)