2009-12-15 2 views
10

Исторически я всегда писал мой Exception код обработки, как это: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 на самом деле взорвать назначение или между назначением и первой строкой того, что находится в блоке try. Я не уверен, что мой старый стиль выдавал дополнительное значение, а второй, безусловно, больше читабельными и лаконичными. Однако литература generally всегда идет с первым стилем.

EDIT - Предположит, я рад за какие-либо исключения брошенных openCursor, а инициализацию курсора не быть пойманным в этом блоке коды, моя единственная забота для этого примера подведения курсора, если он является назначен & открыт. Также предполагаю, что я тестирую нули и т. Д. И т. Д. Yadda ... yadda ... (Я изменил пример, чтобы отразить это, это не было в центре моего вопроса, поэтому я не включил его в первой версии)

+0

++ для Mark, sylvarking, jdmichal & PSpeed. Я отметил, что PSpeed ​​корректен только на основе комментариев о утечке курсоров, и в то время у него было меньше голосов, но в конечном итоге все ответы были полезными. StackOverflow - требуется несколько правильных ответов !? – Joel

ответ

6

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

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

Суть: как написано первая версия излишне сложна. Вторая версия верна.

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

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

Если по какой-либо причине код «// сделать что-то» непреднамеренно очищает переменную курсора, вы будете тихо просачивать курсоры, тогда как раньше вы, по крайней мере, получили исключение NullPointerException. Поскольку дополнительный код абсолютно ничего не полезен, дополнительный риск совершенно не нужен.

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

+0

Обратите внимание, однако, что не проверка на нуль может затруднить отладку сбойного открытия курсора. Если во время открытия курсора возникает исключение, NPE из блока finally отменит исходное исключение. –

+0

Нет ... во втором примере, если open failed, он выдает исключение вне блока try/finally. Единственный способ, по которому курсор может быть нулевым, в конечном итоге - это что-то действительно неправильное произошло внутри try {} ... как плохой локальный код. – PSpeed

0

Если метод openCursor() не генерирует исключение, последнее прекрасно. Если да, то вы обязательно захотите использовать первое. Причина в том, что любое исключение будет передано вызывающему. Если вызывающий метод не настроен для обработки, тогда возникает проблема.

+0

Но если openCursor() терпит неудачу, то нет курсора для закрытия ... переменная курсора даже не имеет значения. – PSpeed

11

(Update:. Вопрос не был скорректирован на основе этого ответа, так что первая часть этого ответа уже не имеет смысла)

Первый пример является неправильным. Он выкинет исключение NullPointerException, если db.openCursor завершится с ошибкой. Второй - лучше.

Кстати, я часто вижу первый метод, как это делается:

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

Это не более безопасно делать это, что делает это ваш второй путь, хотя, но он часто используется в примерах и I Я видел, что он использовал много в реальном коде.

Одна из причин, почему второй метод лучше, заключается в том, что ошибка в коде в разделе // do stuff может установить курсор в значение null, заставив курсор не закрываться и создавая утечку. В целом я не вижу оснований для использования первого метода (даже если он исправлен с нулевой проверкой) и причины, чтобы избежать его использования. Придерживайтесь второго метода.

(Спасибо PSpeed ​​за полезные замечания!)

+1

В этом случае вы должны использовать фигурные скобки. – OscarRyz

+0

Согласен с NPE, но я считаю, что открытие курсора может вызвать исключение, если слишком много открытых (я не мог быстро найти его в документах для подтверждения). Ваш код здесь, вероятно, лучше всего. – cflewis

+0

@ Оскар: Добавлены фигурные скобки. :) –

0

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

+1

Первый стиль не срабатывает аналогичным образом. Только из вашего ответа видно, что это менее очевидно! Второй стиль побеждает. –

+0

@Tom - извините, я не совсем понял, что вы имели в виду под этим комментарием. Я хотел сказать, что вы не хотите использовать второй стиль, если один (или более) аргументов (которые являются «нулями» в примере OP) сам по себе является результатом вызова функции, который может завершиться неудачей. – ChssPly76

13

Я всегда делаю свой второй способ, потому что он позволяет мне установить курсор как 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 и немедленно обработать их там.

6

Нет, вы, наконец, все поняли.

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

1

Там действительно ничего плохого в этом:

Cursor cursor = db.openCursor(null, null); 
    try { 
    // do stuff 
    } finally { 
     try { 
     cursor.close(); 
    } catch(SomeOther so){} 
} 
+2

, вам потребуется поймать (исключение) или (Throwable) или (RuntimeException), чтобы поймать возможный NPE, чего следует избегать. –

0

Разные люди имеют разные opinions.But Рекомендуется использовать первый вариант, потому что если есть какие-либо проблемы открытия курсора, исключение может быть брошено и обработаны Это один из безопасных способов программирования.

Смежные вопросы