Рубрики
Без рубрики

Вопросы собеседования с исключениями Java (ямы)

Набор вопросов собеседования, связанных с исключениями Java.

Автор оригинала: baeldung.

1. Обзор

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

2. Вопросы

No 1. Что такое исключение?

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

S2l Какова цель броска и бросает ключевые слова?

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

public void simpleMethod() throws Exception {
    // ...
}

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

if (task.isTooComplicated()) {
    throw new TooComplicatedException("The task is too complicated");
}

В3. Как вы можете справиться с исключением?

С помощью попробуйте поймать, наконец, утверждение:

try {
    // ...
} catch (ExceptionType1 ex) {
    // ...
} catch (ExceptionType2 ex) {
    // ...
} finally {
    // ...
}

Блок кода, в котором может произойти исключение, заключен в попробуйте блок. Этот блок также называется “защищенный” или “охраняемый” код.

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

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

No 4. Как можно поймать несколько исключений?

В блоке кода есть три способа обработки нескольких исключений.

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

try {
    // ...
} catch (Exception ex) {
    // ...
}

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

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

Второй способ заключается в реализации нескольких блоков улова:

try {
    // ...
} catch (FileNotFoundException ex) {
    // ...
} catch (EOFException ex) {
    // ...
}

Обратите внимание, что, если исключения имеют отношения наследования; тип ребенка должен быть первым, а родительский – позже. Если мы не сделаем этого, это приведет к ошибке компиляции.

Третий заключается в использовании многоулового блока:

try {
    // ...
} catch (FileNotFoundException | EOFException ex) {
    // ...
}

Эта функция, впервые представленная на Java 7; уменьшает дублирование кода и упрощает его обслуживание.

В5 евро. В чем разница между проверенным и неконтролируемым исключением?

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

Проверенные и неконтролируемые исключения также известны как исключения из времени компиляции и времени выполнения соответственно.

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

No 6. В чем разница между исключением и ошибкой?

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

Все ошибки, брошенные JVM являются примерами Ошибка или один из его подклассов, наиболее распространенные из них включают, но не ограничиваются:

  • OutOfMemoryError – бросили, когда JVM не может выделить больше объектов, потому что это из памяти, и сборщик мусора не смог сделать более доступными
  • StackOverflowError — происходит, когда пространство стека для потока закончилось, как правило, потому, что приложение повторяется слишком глубоко
  • ИсключениеInInitializerError – сигнализирует о том, что неожиданное исключение произошло во время оценки статического инициализатора
  • NoClassDefFoundError — брошен, когда классогрузчик пытается загрузить определение класса и не может найти его, как правило, потому, что требуется класс файлы не были найдены в classpath
  • НеподдерживаемыйКлассВерсияЭррор – происходит, когда СПМ пытается прочитать класс файл и определяет, что версия в файле не поддерживается, как правило, потому, что файл был создан с новой версией Java

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

No7. Какое исключение будет брошено при выполнении следующего блока кода?

Integer[][] ints = { { 1, 2, 3 }, { null }, { 7, 8, 9 } };
System.out.println("value = " + ints[1][1].intValue());

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

No 8. Что такое цепь исключений?

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

try {
    task.readConfigFile();
} catch (FileNotFoundException ex) {
    throw new TaskException("Could not perform task", ex);
}

No9. Что такое Stacktrace и как он связан с исключением?

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

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

No10. Почему вы хотите, чтобы subclass исключение?

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

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

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

No11. Каковы некоторые преимущества исключений?

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

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

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

No12. Можете ли вы бросить любое исключение внутри тела выражения Lambda?

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

List integers = Arrays.asList(3, 9, 7, 0, 10, 20);
integers.forEach(i -> {
    if (i == 0) {
        throw new IllegalArgumentException("Zero not allowed");
    }
    System.out.println(Math.PI / i);
});

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

@FunctionalInterface
public static interface CheckedFunction {
    void apply(T t) throws Exception;
}
public void processTasks(
  List taks, CheckedFunction checkedFunction) {
    for (Task task : taks) {
        try {
            checkedFunction.apply(task);
        } catch (Exception e) {
            // ...
        }
    }
}

processTasks(taskList, t -> {
    // ...
    throw new Exception("Something happened");
});

No13. Каковы правила, которые мы должны следовать при переопределении метода, который бросает исключение?

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

Когда метод родительского класса не делает никаких исключений, метод класса ребенка не может сделать какое-либо проверенное исключение, но он может не быть проверен.

Вот пример кода, чтобы продемонстрировать это:

class Parent {
    void doSomething() {
        // ...
    }
}

class Child extends Parent {
    void doSomething() throws IllegalArgumentException {
        // ...
    }
}

Следующий пример не будет компилироваться, так как главный метод бросает проверенное исключение, не объявленное в переопределенном методе:

class Parent {
    void doSomething() {
        // ...
    }
}

class Child extends Parent {
    void doSomething() throws IOException {
        // Compilation error
    }
}

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

Вот пример кода, который успешно следует предыдущему правилу:

class Parent {
    void doSomething() throws IOException, ParseException {
        // ...
    }

    void doSomethingElse() throws IOException {
        // ...
    }
}

class Child extends Parent {
    void doSomething() throws IOException {
        // ...
    }

    void doSomethingElse() throws FileNotFoundException, EOFException {
        // ...
    }
}

Обратите внимание, что оба метода соблюдают правило. Первый бросает меньше исключений, чем переопределенный метод, а второй, даже если он бросает больше; они уже по своим масштабам.

Однако, если мы попытаемся сделать проверенное исключение, которое метод родительского класса не объявляет, или мы бросим его с более широким охватом; Мы получим ошибку компиляции:

class Parent {
    void doSomething() throws FileNotFoundException {
        // ...
    }
}

class Child extends Parent {
    void doSomething() throws IOException {
        // Compilation error
    }
}

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

Вот пример, который выполняет правило:

class Parent {
    void doSomething() throws IllegalArgumentException {
        // ...
    }
}

class Child extends Parent {
    void doSomething()
      throws ArithmeticException, BufferOverflowException {
        // ...
    }
}

No14. Будет ли компилироваться следующий код?

void doSomething() {
    // ...
    throw new RuntimeException(new Exception("Chained Exception"));
}

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

No15. Есть ли способ бросить проверенное исключение из метода, который не имеет положения о бросках?

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

public  T sneakyThrow(Throwable ex) throws T {
    throw (T) ex;
}

public void methodWithoutThrows() {
    this.sneakyThrow(new Exception("Checked Exception"));
}

3. Заключение

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

Мы, в Baeldung, желаем вам успехов в любых предстоящих интервью.