Существует ли предпочтение вложенных блоков попытки/выгоды?

Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals для гарантированного непустого объекта.

Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null.

Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

41
задан yoozer8 9 March 2012 в 15:37
поделиться

10 ответов

Я всегда шел бы для первого примера.

, Если близко должны были выдать исключение (на практике, которого никогда не будет происходить для FileReader), не был бы стандартный способ обработать это для выдачи исключения, соответствующего вызывающей стороне? Близкое исключение почти наверняка превосходит любую проблему, у Вас было использование ресурса. Второй метод является, вероятно, более соответствующим, если Ваша идея обработки исключений состоит в том, чтобы назвать System.err.println.

существует проблема того, как далеко должны быть выданы исключения. ThreadDeath должен всегда повторно бросаться, но любое исключение в наконец остановило бы это. Так же Ошибка должна бросить далее, чем RuntimeException и RuntimeException далее, чем контролируемые исключительные ситуации. Если бы Вы действительно хотели Вам, то мог бы записать, что код, чтобы следовать этим правилам, и затем абстрагировать его с "выполняется вокруг" идиомы.

7
ответ дан emallove 27 November 2019 в 00:55
поделиться

Я боюсь, что существует большая проблема с первым примером, который является, что, если исключение происходит на или после чтения, finally, блок выполняется. Пока неплохо. Но что, если fr.close() тогда причины другое исключение, которое будет брошено? Это "превзойдет" первое исключение (немного как помещение return в finally блок), и Вы потеряете всю информацию о том, что на самом деле вызвало проблему для начала.

Ваш наконец блок должен использовать:

IOUtil.closeSilently(fr);

, где этот служебный метод просто делает:

public static void closeSilently(Closeable c) {
    try { c.close(); } catch (Exception e) {} 
} 
26
ответ дан oxbow_lakes 27 November 2019 в 00:55
поделиться

Я предпочитаю второй. Почему? Если и read() и close() выдают исключения, один из них мог бы быть потерян. В первой конструкции, исключении от close() переопределения исключение от read(), в то время как во втором, исключение от close() обработано отдельно.

<час>

С Java 7, конструкция попытки с ресурсами делает это намного более простым. Для чтения, не заботясь об исключениях:

try (FileReader fr = new FileReader("SomeFile.txt")) {
    fr.read();
    // no need to close since the try-with-resources statement closes it automatically
}

С обработкой исключений:

try (FileReader fr = new FileReader("SomeFile.txt")) {
    fr.read();
    // no need to close since the try-with-resources statement closes it automatically
} catch (IOException e) {
    // Do exception handling
    log(e);
    // If this catch block is run, the FileReader has already been closed.
    // The exception could have come from either read() or close();
    // if both threw exceptions (or if multiple resources were used and had to be closed)
    // then only one exception is thrown and the others are suppressed
    // but can still be retrieved:
    Throwable[] suppressed = e.getSuppressed(); // can be an empty array
    for (Throwable t : suppressed) {
        log(suppressed[t]);
    }
}

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

3
ответ дан Michael Myers 27 November 2019 в 00:55
поделиться

Если и читает и близкий , выдают исключение, исключение от читало , будет скрыт в опции 1. Так, вторая опция делает больше обработки ошибок.

Однако в большинстве случаев, право преимущественной покупки будет все еще предпочтено.

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

, Если необходимо передать все исключительные ситуации, , это может быть сделано .

2
ответ дан McDowell 27 November 2019 в 00:55
поделиться

Различие, насколько я вижу, то, что существуют различные исключения и причины в игре на разных уровнях, и

, выгода (Исключение e)

затеняет это. Единственная точка нескольких уровней должна отличить Ваши исключения, и что Вы сделаете о них:

try
{
  try{
   ...
  }
   catch(IOException e)
  {
  ..
  }
}
catch(Exception e)
{
  // we could read, but now something else is broken 
  ...
}
1
ответ дан Steve B. 27 November 2019 в 00:55
поделиться

Я обычно делаю следующее. Во-первых, определите основанный на шаблонном методе класс для контакта с путаницей попытки/выгоды

import java.io.Closeable;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

public abstract class AutoFileCloser {
    private static final Closeable NEW_FILE = new Closeable() {
        public void close() throws IOException {
            // do nothing
        }
    };

    // the core action code that the implementer wants to run
    protected abstract void doWork() throws Throwable;

    // track a list of closeable thingies to close when finished
    private List<Closeable> closeables_ = new LinkedList<Closeable>();

    // mark a new file
    protected void newFile() {
        closeables_.add(0, NEW_FILE);
    }

    // give the implementer a way to track things to close
    // assumes this is called in order for nested closeables,
    // inner-most to outer-most
    protected void watch(Closeable closeable) {
        closeables_.add(0, closeable);
    }

    public AutoFileCloser() {
        // a variable to track a "meaningful" exception, in case
        // a close() throws an exception
        Throwable pending = null;

        try {
            doWork(); // do the real work

        } catch (Throwable throwable) {
            pending = throwable;

        } finally {
            // close the watched streams
            boolean skip = false;
            for (Closeable closeable : closeables_) {
                if (closeable == NEW_FILE) {
                    skip = false;
                } else  if (!skip && closeable != null) {
                    try {
                        closeable.close();
                        // don't try to re-close nested closeables
                        skip = true;
                    } catch (Throwable throwable) {
                        if (pending == null) {
                            pending = throwable;
                        }
                    }
                }
            }

            // if we had a pending exception, rethrow it
            // this is necessary b/c the close can throw an
            // exception, which would remove the pending
            // status of any exception thrown in the try block
            if (pending != null) {
                if (pending instanceof RuntimeException) {
                    throw (RuntimeException) pending;
                } else {
                    throw new RuntimeException(pending);
                }
            }
        }
    }
}

Примечание "незаконченное" исключение - это заботится о случае, где исключение, выданное во время завершения, замаскировало бы исключение, мы могли бы действительно заботиться о.

наконец пытается закрыться от за пределами любого украшенного потока сначала, поэтому если у Вас был BufferedWriter, обертывающий FileWriter, мы пытаемся закрыть BuffereredWriter сначала, и если это перестало работать, все еще попытайтесь закрыть сам FileWriter.

можно использовать вышеупомянутый класс следующим образом:

try {
    // ...

    new AutoFileCloser() {
        @Override protected void doWork() throws Throwable {
            // declare variables for the readers and "watch" them
            FileReader fileReader = null;
            BufferedReader bufferedReader = null;
            watch(fileReader = new FileReader("somefile"));
            watch(bufferedReader = new BufferedReader(fileReader));

            // ... do something with bufferedReader

            // if you need more than one reader or writer
            newFile(); // puts a flag in the 
            FileWriter fileWriter = null;
            BufferedWriter bufferedWriter = null;
            watch(fileWriter = new FileWriter("someOtherFile"));
            watch(bufferedWriter = new BufferedWriter(fileWriter));

            // ... do something with bufferedWriter
        }
    };

    // .. other logic, maybe more AutoFileClosers

} catch (RuntimeException e) {
    // report or log the exception
}

Используя этот подход Вы никогда не должны волноваться о попытке/выгоде/наконец иметь дело с заключительными файлами снова.

, Если это слишком тяжело для Вашего использования, по крайней мере, думайте о следующем попытка/выгода и "незаконченный" переменный подход, который это использует.

1
ответ дан Scott Stanchfield 27 November 2019 в 00:55
поделиться

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

Это вызвано тем, что, если исключение уже распространяет исключение, выданное из наконец, блок превзойдет исходное исключение (и таким образом будет потерян).

В 99% случаев это не то, что Вы хотите, поскольку исходным исключением является, вероятно, источник Вашей проблемы (любые вторичные исключения могут быть побочными эффектами сначала, но затенят Вашу способность найти источник исходного исключения и таким образом настоящей проблемы).

, Таким образом, Ваш абсолютный код должен быть похожим на это:

try
{
    // Code
}
// Exception handling
finally
{
    // Exception handling that is garanteed not to throw.
    try
    {
         // Exception handling that may throw.
    }
    // Optional Exception handling that should not throw
    finally()
    {}
}
0
ответ дан Martin York 27 November 2019 в 00:55
поделиться

2-й подход.

Иначе, я не вижу, что Вы ловите исключение от конструктора FileReader

http://java.sun.com/j2se/1.5.0/docs/api/java/io/FileReader.html#FileReader (java.lang. Строка)

общедоступный FileReader (Представляют имя файла в виде строки) FileNotFoundException

бросков Так, у меня обычно есть конструктор в блоке попытки также. наконец проверки блока, чтобы видеть, не является ли читатель пустым прежде, чем попытаться сделать завершение.

тот же шаблон идет для Источника данных, Соединения, Оператора, ResultSet.

0
ответ дан anjanb 27 November 2019 в 00:55
поделиться

Иногда вкладываемая выгода попытки не является предпочтением, рассмотрите это:

try{
 string s = File.Open("myfile").ReadToEnd(); // my file has a bunch of numbers
 // I want to get a total of the numbers 
 int total = 0;
 foreach(string line in s.split("\r\n")){
   try{ 
     total += int.Parse(line); 
   } catch{}
 }
catch{}

Это - вероятно, плохой пример, но существуют времена, Вам будет нужна вложенная попытка-cactch.

0
ответ дан Haoest 27 November 2019 в 00:55
поделиться

Мне нравится подход @Chris Маршаллом, но мне никогда не нравится видеть, что исключения глотаются тихо. Я думаю, что его лучшее регистрирует исключения, особенно если Вы - contiuing независимо.

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

я всегда использовал бы регистратор (log4j для меня) для входа ошибок и т.д.

IOUtil.close(fr);

А небольшая модификация к служебному методу:

public static void close(Closeable c) {
    try {
      c.close();
    } catch (Exception e) {
      logger.error("An error occurred while closing. Continuing regardless", e); 
    } 
}
0
ответ дан Dunderklumpen 27 November 2019 в 00:55
поделиться
Другие вопросы по тегам:

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