Десять советов по обработке исключений в Java

Java

предисловие

Десять предложений по обработке исключений Java, надеюсь, они вам помогут~

Эта статья была загружена на github:

GitHub.com/Я бы хотел 123/Java…

Общественный номер: маленький мальчик собирает улиток

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 впереди ~

публика

  • Добро пожаловать, чтобы обратить внимание на мой личный публичный аккаунт, подружиться и учиться вместе ~
  • Если ответ неверный, укажите на это, большое спасибо~