Как избежать использования блоков try ... catch - PullRequest
5 голосов
/ 06 февраля 2012

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

public void iterateComparatorResults(ArrayList<ComparatorValue> results) throws IOException, IllegalArgumentException, IntrospectionException, IllegalAccessException, InvocationTargetException {
    Iterator<ComparatorValue> iterator = results.iterator();
    for(int i=0; i<results.size(); i++) {
        //Set data variables.
        setBeans(results.get(i).getClientBean(), results.get(i).getServerBean());
        setValues(results.get(i).getClientValue(), results.get(i).getServerValue());

        if(results.get(i).isMatch()) {
            //Data matches.
            runIteratorTrueAction();
        } else if(results.get(i).getInnerBeans() != null){
            //Value is a nested bean. Iterate again.
            ArrayList<ArrayList<ComparatorValue>> innerResults = results.get(i).getInnerBeans();
            for(int r=0; r<innerResults.size(); r++) {
                iterateComparatorResults(innerResults.get(r));
            }

        } else {
            //Data does not match.
            runIteratorFalseAction();
        }
    }
}

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

try {
    beanComparator.setIteratorFalseAction(falseAction);
                beanComparator.iterateComparatorResults(beanComparator.compareBeans(contact, compareContact));
} catch (IllegalArgumentException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} catch (IntrospectionException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}

Я надеюсь, что есть какой-то шаблон проектирования, который я могу реализовать, чтобы я мог создать отдельный класс или что-то еще и скрыть все блоки try в одном месте, затем ссылаться на этот класс и использовать блоки try безнаписать их.Подобно тому, как это делают другие фреймворки, такие как Spring?Мне просто нужно небольшое руководство о том, как это сделать, поскольку я даже не знаю, с чего начать.

Ответы [ 6 ]

8 голосов
/ 06 февраля 2012

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

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

Я следую двум общим принципам:

  1. Обрабатывайте исключение в том месте, в котором оно было сгенерировано, если выможет (например, закрыть открытый файл на исключение доступа к файлу или повторить проблемный интерфейс ( глупые ненадежные устройства USB на заказ ... )).
  2. Разрешить исключению пузыриться до уровня выше в вашем стеке, где вы можете перехватывать все исключения, которые иначе не сможете обработать.Регистрируйте их, отображайте или убивайте свое приложение, что бы ни имело смысла.

Я проиллюстрирую вторую точку с помощью некоторого кода, украденного из , вдохновленного уроками Java .

private String readFirstLineFromFile(String path) throws IOException
{
    try (BufferedReader br = new BufferedReader(new FileReader(path)))
    {
        return br.readLine();
    }
}

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

private String readAllTheFiles() throws IOException
{
    for (...)
    {
        readFirstLineFromFile(...);
    }
}

Теперь есть много споров вокругпочему Java требует throws в этом случае.Многие другие языки не используют их, к лучшему или худшему.Вы часто будете видеть RuntimeExceptions - исключения, которые не требуют предложения throws.Если ваш метод может выдать исключение, которое простирается от RuntimeException, вам не нужно объявлять этот факт в throws.

4 голосов
/ 06 февраля 2012

Если вы используете JDK-7, вы можете обернуть блок захвата следующим образом

catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
} 
2 голосов
/ 06 февраля 2012

Все исключения расширяют класс Exception (кое-что, как по ходу дела), поэтому вы можете сделать следующее:

try {
    sql = (SQL) MethodUtils.invokeExactMethod(bean, "getSQL", (Object[])null);
} catch (Exception e) {
    e.printStackTrace();
} 

Вы также можете добавить оператор throws к методам, чтобы тот, кто вызывает ваши методы класса, могдобавьте попытку в их код.

void myMethod() throws NoSuchMethodException, IllegalAccessException,
                       InvocationTargetException {
    //  Do stuff that can throw an exception.
}
0 голосов
/ 06 февраля 2012

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

try {
    sql = (SQL) MethodUtils.invokeExactMethod(bean, "getSQL", (Object[])null);
} catch (Exception e) {
    throw new InvocationFaliureException(e);
}

здесь InvocationFaliureExceptionпользовательское исключение,

public InvocationFaliureException extends Exception
{
....
}
0 голосов
/ 06 февраля 2012

Если вы используете Java 7, вы можете использовать перехват нескольких исключений . Это упростит код до этого:

try {
    sql = (SQL) MethodUtils.invokeExactMethod(bean, "getSQL", (Object[])null);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
    e.printStackTrace();
}

Это лучше, чем просто перехватывать исключения, так как вы все еще ловите только те исключения, которые хотите.

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

0 голосов
/ 06 февраля 2012

Вы можете поймать их и выбросить их как RuntimeException, например так ...

 try {
     sql = (SQL) MethodUtils.invokeExactMethod(bean, "getSQL", (Object[])null);
 } catch(Exception e){
     throw new RuntimeException(e);
 }
...