Обработка исключений, возникающих в блоках инициализации в Java

Этот пост является продолжением изучения малоизвестных возможностей Java. В предыдущем посте я рассмотрел несколько весьма неожиданных случаев использования класса sun.misc.Unsafe. В этом посте я обсуждаю малоизвестную возможность блоков инициализаторов.

1. Блоки инициализатора

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

Инициализаторы можно использовать двумя способами:

  • Блок инициализации экземпляра: он зависит от объекта, и блок инициализации выполняется для каждого объекта класса, который создается. Он может инициализировать переменные-члены экземпляра класса.
  • Статический блок инициализатора: он определяется с помощью ключевого слова static и выполняется один раз при загрузке класса, а также имеет ограничение, заключающееся в том, что он может инициализировать только статические члены данных класса.

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

2. Блоки инициализатора могут вызывать исключения

Иногда в блоке инициализатора вам может понадобиться написать некоторый код, который может выдавать проверенные исключения. Проверенные исключения — это те исключения, которые проверяются во время компиляции, и компилятор заставляет вас обрабатывать их в вашем коде. Давайте рассмотрим пример:

public class CheckedExceptionsFromConstrctor {Document doc = null;{doc = new SAXBuilder(false).build(new StringReader(new String("<users>")));}}

Приведенный выше код выдает два проверенных исключения: IOException и JDOMException. Мы можем обработать их с помощью try-catch. Например

public class CheckedExceptionsFromConstrctor {Document doc = null;try {doc = new SAXBuilder(false).build(new StringReader(new String("<users>")));} catch(JDOMException | IOException e) {e.printStackTrace();}}

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

public class CheckedExceptionsFromConstrctor {Document doc = null;try {doc = new SAXBuilder(false).build(new StringReader(new String("<users>")));} catch(JDOMException | IOException e) {throw e; //Not allowed}}

3. Объявление исключений из инициализаторов экземпляров в конструкторе

Добавьте предложение throws в конструкторы, и вы сможете выбрасывать проверяемые исключения из инициализаторов. Например:

public class CheckedExceptionsFromConstrctor {Document doc = null;public CheckedExceptionsFromConstrctor() throws IOException, JDOMException {//constructor}{doc = new SAXBuilder(false).build(new StringReader(new String("<users>")));}}

4. Статические инициализаторы не могут вызывать проверяемые исключения.

Приведенное выше обоснование было для нестатических или инициализаторов экземпляров. Если в вашем классе есть статические инициализаторы, то вы ДОЛЖНЫ обрабатывать проверяемые исключения. Вам не разрешено выбрасывать их любым возможным способом.

public class CheckedExceptionsFromConstrctor{static Document doc = null;public CheckedExceptionsFromConstrctor() {//Some other code}static {try {doc = new SAXBuilder(false).build(new StringReader(new String("<users>")));} catch(JDOMException | IOException e) {e.printStackTrace(); //You must handle the exception here}}}

Вот и все по этой теме. Надеюсь, вам понравилось. Буду признателен, если вы поделитесь своими мыслями в комментариях. И не забудьте подписаться по электронной почте, чтобы получать новые обновления по таким малоизвестным функциям.

Прокрутить вверх