Java принудительно ловит RuntimeException? - PullRequest
4 голосов
/ 30 апреля 2010

Можно ли заставить java заставить вас перехватывать RuntimeExceptions?В частности, я работаю со средой Spring, и вся иерархия исключений основана на исключениях RuntimeException.Много раз я забываю пытаться поймать исключения.Конкретным примером является выполнение запроса LDAP или вызова SQL.

Ответы [ 9 ]

7 голосов
/ 30 апреля 2010

Не только с Java.

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

Определение аспекта из Википедия :

аспект является частью программы, которая решает основные проблемы

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

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

Это всего лишь пример. Вы можете изменить его, чтобы перехватывать RuntimeExceptions в других местах. Например, во всех методах, которые находятся внутри класса, в имени которого есть Facade и который вызывает другие методы. Смотрите картинку ниже для идей:

альтернативный текст http://files.espenberntsen.net/stackoverflow/call-to-integration-layer.png Оранжевые стрелки - мой pointpect AspectJ, проиллюстрированный с помощью плагина AJDT в Eclipse. Это места, где вы можете поймать и справиться с исключениями времени выполнения в AfterThrowing рекомендации.

Вот совет:

@AfterThrowing(value="serviceMethodAfterExpcetionFromIntegrationLayerPointcut()",     
     throwing="e")
public void serviceMethodAfterExceptionFromIntegrationLayer(JoinPoint joinPoint,
  RuntimeException e) {
  StringBuilder arguments = generateArgumentsString(joinPoint.getArgs());

  logger.error("Error in service " + joinPoint.getSignature()
  + " with the arguments: " + arguments, e);
  }

My serviceMethodAfterExpcetionFromIntegrationLayerPointcut фактически состоит из двух других точек:

 @Pointcut("call(* *..integration.*.*(..))")
 public void integrationLayerPointcut() {}

 @Pointcut("within(@org.springframework.stereotype.Service *)")
 public void serviceBean() {}

 @Pointcut("serviceBean() && integrationLayerPointcut()")
 public void serviceMethodAfterExpcetionFromIntegrationLayerPointcut() {}

Вкратце, pointcut находит все места в классах, помеченных аннотацией @Service, которые вызывают метод в классе на уровне интеграции. (См. Оранжевые стрелки на картинке)

Если вы хотите вместо этого перехватывать исключения во время выполнения в своих тестовых классах, вы можете изменить точку на это:

@Pointcut("within(com.redpill.linpro.demo..*Test)")
public void inDemoProjectTestClass() {}

Тогда приведенный выше совет перехватит все исключения в тестовых классах, которые заканчиваются на Test в пакете ..demo.

Дополнительная информация о @ AspectJ style здесь .

AspectJ хорошо интегрируется с Spring. Общую информацию об AspectJ можно найти здесь и поддержку Spring AspectJ здесь .

5 голосов
/ 30 апреля 2010

Нет: RuntimeException и его подклассы являются непроверенными исключениями.

JLS 11.2.5 Почему исключения во время выполнения не проверяются

Классы исключения времени выполнения (RuntimeException и его подклассы) освобождаются от проверки во время компиляции, поскольку, по мнению разработчиков языка программирования Java, необходимость объявления таких исключений не будет значительно в установлении правильности программ. Многие операции и конструкции языка программирования Java могут привести к исключениям во время выполнения. Информация, доступная компилятору, и уровень анализа, выполняемого компилятором, обычно недостаточны для того, чтобы установить, что такие исключения во время выполнения не могут возникнуть, даже если это может быть очевидно для программиста. Требование, чтобы такие классы исключений были объявлены, было бы просто раздражением для программистов.

JLS 11.5 Иерархия исключений

Класс Exception является суперклассом всех исключений, из которых обычные программы могут захотеть восстановиться. Класс RuntimeException является подклассом класса Exception. Подклассы RuntimeException являются непроверенными исключениями классов. Подклассы Exception, отличные от RuntimeException, и все его подклассы проверены классы исключений.

2 голосов
/ 30 апреля 2010

Нет. Подклассы RuntimeException никогда не проверяются.

1 голос
/ 30 апреля 2010

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

Более того, с проверенными исключениями ваш код становится более запутанным и неуклюжим, особенно если вам нужен еще один блок try / catch в блоке catch.

0 голосов
/ 10 октября 2012

RuntimeExceptions может быть перехвачен и обработан как Проверенные Исключения, но они не должны быть обработаны. Например, если вы добавите новое NullPointerException () в блок try, компилятор не заставит вас указывать ключевое слово throws в объявлении метода, как при создании исключения Checked. Обработка RuntimeException или его подкласса указывает на плохой стиль программирования, и его следует избегать.

0 голосов
/ 30 апреля 2010

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

Так что вместо того, чтобы заставлять вспоминать

 try {
    SpringThing.doThatOneMethod();
 catch (SpringConnectionException sce) { /*handle it*/ }
 catch (SpringProxyException      spe) { /*handle it*/ }
 catch (SpringRuntimeException    sre) { /*handle it*/ }

, вы всегда можете вызвать свой собственный SpringExceptionsWrapper.doThatOneMethod().

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

0 голосов
/ 30 апреля 2010

Нет. Единственное, о чем я могу подумать, - это использовать такой инструмент, как FindBugs, PMD и т. Д., Чтобы найти эти проблемы для вас, хотя я не верю, что у какого-либо инструмента есть специальный инструмент для этого. Вы можете написать свой собственный детектор однако. Конечно, это применимо только к явному выбрасыванию исключений RuntimeException, а не к неявным, например NullPointerException.

0 голосов
/ 30 апреля 2010

Нет, это невозможно.

То, что вы могли бы сделать, но плохой дизайн и определенно не рекомендуется , это то, что вы заставили метод бросить Exception

public void doStuff() throws Exception {}

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

0 голосов
/ 30 апреля 2010

Нет, вы не можете заставить компилятор заставить вас поймать RuntimeException.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...