Обработка исключений Java - стиль

Исторически я всегда писал свой код Обработки исключений как это:

    Cursor cursor = null;
    try {
        cursor = db.openCursor(null, null);
        // do stuff
    } finally {
        if (cursor != null) cursor.close();
    }

Но недавно, по причинам удобочитаемости и лени, я начал делать это:

        Cursor cursor = db.openCursor(null, null);
        try {           
            // do stuff
        } finally {
            cursor.close();
        }

Разве я неправ иметь присвоение на курсор (jdbc дескриптор, безотносительно) из try-catch-finally блока?

При запрете JVM, на самом деле аварийно завершающейся на присвоении или промежутке присвоение и первая строка того, что находится в блоке попытки, я не уверен, предоставлял ли мой старый стиль какое-либо дополнительное значение, и второе, конечно, более читаемо и кратко. Литература обычно всегда идет с первым стилем все же.

РЕДАКТИРОВАНИЕ - предполагает, что я счастлив за любые исключения, выданные openCursor при инициализации курсора, который не будет пойман в этом блоке кода, мое единственное беспокойство об этом примере закрывает курсор, если это присвоено и открыто. Также предположите, что я тестирую на пустые указатели и т.д. и т.д. yadda... yadda... (Я изменил пример для отражения этого, это не был фокус моего вопроса, таким образом, я не включал его в первую версию),

10
задан Joel 15 December 2009 в 19:23
поделиться

7 ответов

Если все, что вы делаете в final, закрывает курсор, то вторая форма верна. У вас никогда не будет курсора, который нужно закрыть, если openCursor () завершится неудачно. Значение этой переменной даже не будет установлено.

Как упоминают другие, предостережения заключаются в том, что если вы выполняете дополнительную инициализацию, которая требует своей собственной очистки, то это, по логике, должно быть введено в finally {} и изменено объем соответственно. Хотя в этом случае я бы выступил за реструктуризацию.

Итог: как написано, первая версия излишне сложна. Вторая версия верна.

Edit: Включая мои другие комментарии для потомков ...

Первый пример может показаться безобидным, поскольку все, что он делает, это добавляет кучу ненужного кода. (Совершенно ненужно, если это непонятно.) Однако в классике " дополнительный риск совершенно не нужен.

Поэтому я готов назвать первый пример «просто неправильным». Я бы обязательно отметил это при проверке кода.

дополнительный риск совершенно не нужен.

Поэтому я готов назвать первый пример «просто неправильным». Я бы обязательно отметил это при проверке кода.

6
ответ дан 3 December 2019 в 14:06
поделиться

Я всегда использую второй способ, потому что он позволяет мне установить курсор как final . Нет причин, по которым я могу видеть назначение в предложении try, если вы на самом деле не пытаетесь перехватить из него исключения.

РЕДАКТИРОВАТЬ: Просто обратите внимание, из дальнейшего обсуждения, которое было продолжено. Вот как я бы обработал вызов openCursor , генерирующий исключение:

try
{
    // ALLOCATE RESOURCE
    final Cursor cursor = db.openCursor(null, null);

    try
    {
        // USE RESOURCE
    }
    finally
    {
        // DISPOSE RESOURCE
        cursor.close();
    }
}
catch(OpenCursorException e)
{
    // Handle this appropriately.
}

Обратите внимание на четкое разделение выделения, использования и удаления. Единственный раз, когда это становится немного интересным, - это если использование блока try вызывает то же исключение, которое вы улавливаете для блока распределения try . ( IOException может быть особенно хорошим примером этого, поскольку открытие и чтение могут вызвать одно и то же.) В этом случае все будет по-прежнему очищаться и утилизироваться правильно, но вы можете неправильно отнести сбой к исключению инициализации, а не к исключению использования. В этом случае вам нужно перехватить исключение (я) во внутреннем блоке try и сразу же обработать их там.

13
ответ дан 3 December 2019 в 14:06
поделиться

(Update: the question was corrected based on this answer, so the first part of this answer no longer makes sense.)

The first example is wrong. It will throw a NullPointerException if db.openCursor fails. The second is better.

By the way, I often see the first method done like this:

Cursor cursor = null;
try {
    cursor = db.openCursor(null, null);
    // do stuff
} finally {
    if (cursor != null) {
        cursor.close();
    }
}

It isn't more safe doing this that doing it your second way though, but it is often used in examples and I've seen it used a lot in real code.

One reason why the second method is better is that a bug in the code in the // do stuff section can set the Cursor to null, causing the cursor to not be closed and creating a leak. All in all I can see no good reasons to use the first method (even when it is corrected with the null check), and reasons to avoid using it. Stick to the second method.

(Thanks to PSpeed for the useful comments!)

11
ответ дан 3 December 2019 в 14:06
поделиться

Создание регулярного выражения для соответствия диапазону произвольных чисел http://utilitymill.com/utility/Regex_For_Range

дает следующее выражение регулярного выражения:

\b0*([0-9]{1,4}|[1-7][0-9]{4}|8[0-5][0-9]{3}|86[0-3][0-9]{2}|86400)\b

Описание вывода:

First, break into equal length ranges:
  0 - 9
  10 - 99
  100 - 999
  1000 - 9999
  10000 - 86400

Second, break into ranges that yield simple regexes:
  0 - 9
  10 - 99
  100 - 999
  1000 - 9999
  10000 - 79999
  80000 - 85999
  86000 - 86399
  86400 - 86400

Turn each range into a regex:
  [0-9]
  [1-9][0-9]
  [1-9][0-9]{2}
  [1-9][0-9]{3}
  [1-7][0-9]{4}
  8[0-5][0-9]{3}
  86[0-3][0-9]{2}
  86400

Collapse adjacent powers of 10:
  [0-9]{1,4}
  [1-7][0-9]{4}
  8[0-5][0-9]{3}
  86[0-3][0-9]{2}
  86400

Combining the regexes above yields:
  0*([0-9]{1,4}|[1-7][0-9]{4}|8[0-5][0-9]{3}|86[0-3][0-9]{2}|86400)

Проверено здесь: в данном случае), чтобы подавить предупреждения компилятора об использовании неинициализированных переменных. Вместо этого прислушайтесь к предупреждению и правильно инициализируйте свои переменные - как показывает ваш второй, «ленивый» пример.

6
ответ дан 3 December 2019 в 14:06
поделиться

There is really nothing wrong in doing :

Cursor cursor = db.openCursor(null, null);  
  try {  
     // do stuff  
   } finally {  
      try {  
        cursor.close();  
     } catch( SomeOther so ){}  
 }  
1
ответ дан 3 December 2019 в 14:06
поделиться

If the openCursor() method doesn't throw an exception, the latter is fine. If it does, then you would definitely want to use the former. The reason being that any exception would be thrown to the caller. If the calling method isn't set up to handle that then there is an issue.

0
ответ дан 3 December 2019 в 14:06
поделиться

The second style is fine as long as neither of the method arguments is a calculated expression that can throw its own exception and needs cleaning up after.

0
ответ дан 3 December 2019 в 14:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: