предисловие
Десять предложений по обработке исключений Java, надеюсь, они вам помогут~
Эта статья была загружена на github:
Общественный номер: маленький мальчик собирает улиток
1. Старайтесь не использовать e.printStackTrace(), а используйте печать журнала.
Пример счетчика:
try{
// do what you want
}catch(Exception e){
e.printStackTrace();
}
Положительный пример:
try{
// do what you want
}catch(Exception e){
log.info("你的程序有异常啦,{}",e);
}
причина:
- Журнал стека, напечатанный функцией printStackTrace(), чередуется с журналом бизнес-кода, и обычно неудобно устранять неполадки в журналах исключений.
- Строка, сгенерированная оператором e.printStackTrace(), записывает информацию о стеке.Если информация слишком длинная, в блоке памяти, где находится пул строковых констант, нет места, то есть память заполнена, то запрос пользователя будет застрять~
2. Исключение перехватывается, но конкретное исключение не распечатывается, поэтому проблема не может быть лучше локализована.
Пример счетчика:
try{
// do what you want
}catch(Exception e){
log.info("你的程序有异常啦");
}
Положительный пример:
try{
// do what you want
}catch(Exception e){
log.info("你的程序有异常啦,{}",e);
}
причина:
- В контрпримере исключение не выводится, и исследовать проблему в это время будет сложно.Это исключение, написанное SQl неправильно, исключение IO или что-то еще? Таким образом, исключение должно быть напечатано в журнале~
3. Не используйте Exception для перехвата всех возможных исключений
Пример счетчика:
public void test(){
try{
//…抛出 IOException 的代码调用
//…抛出 SQLException 的代码调用
}catch(Exception e){
//用基类 Exception 捕捉的所有可能的异常,如果多个层次都这样捕捉,会丢失原始异常的有效信息哦
log.info(“Exception in test,exception:{}”, e);
}
}
Положительный пример:
public void test(){
try{
//…抛出 IOException 的代码调用
//…抛出 SQLException 的代码调用
}catch(IOException e){
//仅仅捕捉 IOException
log.info(“IOException in test,exception:{}”, e);
}catch(SQLException e){
//仅仅捕捉 SQLException
log.info(“SQLException in test,exception:{}”, e);
}
}
причина:
- Все возможные исключения, захваченные исключением базового класса, если в этом случае используются несколько уровней, эффективная информация оригинального исключения будет потеряна.
В-четвертых, не забудьте использовать finally, чтобы закрыть ресурс потока или напрямую использовать try-with-resource.
Пример счетчика:
FileInputStream fdIn = null;
try {
fdIn = new FileInputStream(new File("/jay.txt"));
//在这里关闭流资源?有没有问题呢?如果发生异常了呢?
fdIn.close();
} catch (FileNotFoundException e) {
log.error(e);
} catch (IOException e) {
log.error(e);
}
Положительный пример 1:
Вам нужно использовать finally, чтобы закрыть ресурс потока, как показано ниже.
FileInputStream fdIn = null;
try {
fdIn = new FileInputStream(new File("/jay.txt"));
} catch (FileNotFoundException e) {
log.error(e);
} catch (IOException e) {
log.error(e);
}finally {
try {
if (fdIn != null) {
fdIn.close();
}
} catch (IOException e) {
log.error(e);
}
}
Положительный пример 2:
Конечно, с этим также можно справиться с помощью try-with-resource, новой функции JDK7, которая представляет собой новую функцию, предоставляемую Java7 для автоматического управления ресурсами.
- Ресурс — это объект, который должен быть закрыт после того, как программа израсходована.
- try-with-resources гарантирует, что каждый объявленный ресурс будет закрыт в конце оператора
- Какие объекты можно использовать в качестве ресурсов? Пока объект, реализующий интерфейс java.lang.AutoCloseable или интерфейс java.io.Closeable, в порядке.
try (FileInputStream inputStream = new FileInputStream(new File("jay.txt")) {
// use resources
} catch (FileNotFoundException e) {
log.error(e);
} catch (IOException e) {
log.error(e);
}
причина:
- Если не использовать finally или try-with-resource, то при возникновении исключения в программе и незакрытом потоке IO-ресурса, IO-ресурс будет занят им все время, так что другие не смогут использовать это приведет к пустой трате ресурсов.
5. Перехваченное исключение и выброшенное исключение должны точно совпадать, иначе перехваченное исключение является родительским классом выброшенного исключения.
Пример счетчика:
//BizException 是 Exception 的子类
public class BizException extends Exception {}
//抛出父类Exception
public static void test() throws Exception {}
try {
test(); //编译错误
} catch (BizException e) { //捕获异常子类是没法匹配的哦
log.error(e);
}
Положительный пример:
//抛出子类Exception
public static void test() throws BizException {}
try {
test();
} catch (Exception e) {
log.error(e);
}
6. Пойманное исключение нельзя игнорировать, хоть лог сделай
Пример счетчика:
public static void testIgnoreException() throws Exception {
try {
// 搞事情
} catch (Exception e) { //一般不会有这个异常
}
}
Положительный пример:
public static void testIgnoreException() {
try {
// 搞事情
} catch (Exception e) { //一般不会有这个异常
log.error("这个异常不应该在这里出现的,{}",e);
}
}
причина:
- Хотя это исключение, которое не происходит при нормальных обстоятельствах, если вы его поймаете, не игнорируйте его, по крайней мере, сделайте журнал~
7. Обратите внимание на вторжение исключений в вашу иерархию кода (раннее обнаружение и раннее лечение)
Пример счетчика:
public UserInfo queryUserInfoByUserId(Long userid) throw SQLException {
//根据用户Id查询数据库
}
Положительный пример:
public UserInfo queryUserInfoByUserId(Long userid) {
try{
//根据用户Id查询数据库
}catch(SQLException e){
log.error("查询数据库异常啦,{}",e);
}finally{
//关闭连接,清理资源
}
}
причина:
- В наших проектах код обычно делится на различные иерархические структуры, такие как Action, Service, Dao и т. д. Если вы являетесь исключением, которое обрабатывается на уровне DAO, обработайте его как можно скорее. код все еще нужно попробовать поймать.Это загрязняет ваш код~
Восемь, пользовательское исключение пакета, не отбрасывайте исходную информацию об исключении.
Мы часто хотим сгенерировать исключение после перехвата другого и хотим сохранить информацию об исходном исключении, что называется цепочкой исключений. Фреймворк компании обеспечивает унифицированную обработку исключений и использует цепочку исключений.Мы настраиваем исключение пакета, не отбрасываем исходную информацию об исключении, иначе устранить проблему будет головной болью.
Пример счетчика:
public class TestChainException {
public void readFile() throws MyException{
try {
InputStream is = new FileInputStream("jay.txt");
Scanner in = new Scanner(is);
while (in.hasNext()) {
System.out.println(in.next());
}
} catch (FileNotFoundException e) {
//e 保存异常信息
throw new MyException("文件在哪里呢");
}
}
public void invokeReadFile() throws MyException{
try {
readFile();
} catch (MyException e) {
//e 保存异常信息
throw new MyException("文件找不到");
}
}
public static void main(String[] args) {
TestChainException t = new TestChainException();
try {
t.invokeReadFile();
} catch (MyException e) {
e.printStackTrace();
}
}
}
//MyException 构造器
public MyException(String message) {
super(message);
}
Результаты операции таковы: без причины Throwable трудно исследовать, что является ненормальным.
Положительный пример:
public class TestChainException {
public void readFile() throws MyException{
try {
InputStream is = new FileInputStream("jay.txt");
Scanner in = new Scanner(is);
while (in.hasNext()) {
System.out.println(in.next());
}
} catch (FileNotFoundException e) {
//e 保存异常信息
throw new MyException("文件在哪里呢", e);
}
}
public void invokeReadFile() throws MyException{
try {
readFile();
} catch (MyException e) {
//e 保存异常信息
throw new MyException("文件找不到", e);
}
}
public static void main(String[] args) {
TestChainException t = new TestChainException();
try {
t.invokeReadFile();
} catch (MyException e) {
e.printStackTrace();
}
}
}
//MyException 构造器
public MyException(String message, Throwable cause) {
super(message, cause);
}
9. Исключение во время выполнения RuntimeException не должно обрабатываться с помощью catch, а предварительно проверяться, например: обработка исключений NullPointerException
Пример счетчика:
try {
obj.method()
} catch (NullPointerException e) {
...
}
Положительный пример:
if (obj != null){
...
}
10. Обратите внимание на порядок сопоставления исключений и отдайте приоритет перехвату конкретных исключений.
Обратите внимание на порядок сопоставления исключений, потому что будет выполнен только первый блок catch, соответствующий исключению. Сбросьте NumberFormatException, если вы хотите увидеть NumberFormatException, и IllegalArgumentException, если это IllegalArgumentException.
Пример счетчика:
try {
doSomething("test exception");
} catch (IllegalArgumentException e) {
log.error(e);
} catch (NumberFormatException e) {
log.error(e);
}
Положительный пример:
try {
doSomething("test exception");
} catch (NumberFormatException e) {
log.error(e);
} catch (IllegalArgumentException e) {
log.error(e);
}
причина:
- Поскольку NumberFormatException является подклассом IllegalArgumentException, в встречном примере, независимо от того, какое это исключение, оно будет соответствовать IllegalArgumentException и не будет выполнено, поэтому я не знаю, является ли это NumberFormatException. Поэтому вам нужно сначала поймать определенные исключения и поставить NumberFormatException впереди ~
публика
- Добро пожаловать, чтобы обратить внимание на мой личный публичный аккаунт, подружиться и учиться вместе ~
- Если ответ неверный, укажите на это, большое спасибо~