условиях Является ли блок finally всегда исполняемым на Java?




при каких условиях блок finally не будет выполнен (24)

Ответ прост ДА .

ВХОД:

try{
    int divideByZeroException = 5 / 0;
} catch (Exception e){
    System.out.println("catch");
    return;    // also tried with break; in switch-case, got same output
} finally {
    System.out.println("finally");
}

ВЫХОД:

catch
finally

Учитывая этот код, могу ли я быть абсолютно уверенным, что блок finally всегда выполняется, вне зависимости от того, something() что- something() ?

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("i don't know if this will get printed out.");
}

Кроме того, хотя это плохая практика, если в блоке finally есть оператор return, он будет превзойти любой другой возврат из обычного блока. То есть, следующий блок вернет false:

try { return true; } finally { return false; }

То же самое с бросанием исключений из блока finally.


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


наконец, выполняется всегда, если нет ненормального завершения программы (например, вызов System.exit (0) ..). поэтому ваш sysout будет распечатан


Наконец, это всегда работает, и это все, только потому, что оно появляется в коде после возвращения, не означает, что так оно и было реализовано. Среда выполнения Java несет ответственность за запуск этого кода при выходе из блока try .

Например, если у вас есть следующее:

int foo() { 
    try {
        return 42;
    }
    finally {
        System.out.println("done");
    }
}

Среда выполнения создаст что-то вроде этого:

int foo() {
    int ret = 42;
    System.out.println("done");
    return 42;
}

Если выбрано неперехваченное исключение, блок finally будет запущен, и исключение продолжит распространение.



Вкратце, в официальной документации Java (нажмите here ) написано, что -

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


Да, это будет. Независимо от того, что происходит в вашем блоке try или catch, если иное не вызвано вызовом System.exit () или JVM. если в блоке (-ах) есть какой-либо оператор возврата, он, наконец, будет выполнен до этого оператора return.


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


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


Да, это будет. Только в случае, если это не произойдет, произойдет JVM или сбой


Я попробовал приведенный выше пример с небольшими изменениями -

public static void main(final String[] args) {
    System.out.println(test());
}

public static int test() {
    int i = 0;
    try {
        i = 2;
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
    }
}

Вышеуказанные выходы кода:

наконец, козыри возвращаются.
2

Это связано с тем, что при return i; выполняется i имеет значение 2. После этого выполняется блок finally где 12 назначается i а затем выполняется System.out out.

После выполнения блока finally блок try возвращает 2, а не возвращает 12, потому что этот оператор возврата не выполняется снова.

Если вы отлаживаете этот код в Eclipse, тогда вы почувствуете, что после выполнения System.out finally блока оператор return будет выполнен снова. Но это не так. Он просто возвращает значение 2.


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

Только время, когда он не запускается, - это когда JVM завершает работу.


В дополнение к другим ответам важно указать, что «наконец» имеет право переопределить любое исключение / возвращаемое значение блоком try..catch. Например, следующий код возвращает 12:

public static int getMonthsInYear() {
    try {
        return 10;
    }
    finally {
        return 12;
    }
}

Аналогичным образом, следующий метод не генерирует исключения:

public static int getMonthsInYear() {
    try {
        throw new RuntimeException();
    }
    finally {
        return 12;
    }
}

Хотя следующий метод действительно бросает его:

public static int getMonthsInYear() {
    try {
        return 12;          
    }
    finally {
        throw new RuntimeException();
    }
}

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


Да, он будет вызван. В этом весь смысл наличия ключевого слова finally. Если выпрыгнуть из блока try / catch можно просто пропустить блок finally, это было бы то же самое, что и поставить System.out.println вне try / catch.


Рассмотрим следующую программу:

public class someTest {

    private static StringBuilder sb = new StringBuilder();

    public static void main(String args[]) {

        System.out.println(someString());
        System.out.println("---AGAIN---");
        System.out.println(someString());
    }

    private static String someString() {

        try {
            sb.append("-abc-");
            return sb.toString();

        } finally {
            sb.append("xyz");
        }
    }
}

Начиная с Java 1.8.162, приведенный выше блок кода дает следующий результат:

-abc-
---AGAIN---
-abc-xyz-abc-

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

private static String someString() {

    StringBuilder sb = new StringBuilder();

    try {
        sb.append("abc");
        return sb.toString();

    } finally {
        sb = null;
    }
}

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

Наконец, вызывается независимо от того, что происходит в блоке try ( если вы не вызываете System.exit(int) или виртуальную машину Java не запускается по какой-либо другой причине).


Рассмотрите это в обычном ходе выполнения (т. Е. Без какого-либо исключения): если метод не является «void», он всегда явно возвращает что-то, но, наконец, всегда выполняется


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


Нет, не всегда один случай исключения // System.exit (0); прежде чем блок finally предотвратит, наконец, выполнение.

  class A {
    public static void main(String args[]){
        DataInputStream cin = new DataInputStream(System.in);
        try{
            int i=Integer.parseInt(cin.readLine());
        }catch(ArithmeticException e){
        }catch(Exception e){
           System.exit(0);//Program terminates before executing finally block
        }finally{
            System.out.println("Won't be executed");
            System.out.println("No error");
        }
    }
}

Вот выработка ответа Кевина . Важно знать, что выражение, которое будет возвращено, оценивается до, finally , даже если оно возвращается после.

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int printX() {
    System.out.println("X");
    return 0;
}

public static int test() {
    try {
        return printX();
    }
    finally {
        System.out.println("finally trumps return... sort of");
    }
}

Выход:

X
finally trumps return... sort of
0

Это связано с тем, что вы назначили значение i как 12, но не возвращали значение i в функцию. Правильный код выглядит следующим образом:

public static int test() {
    int i = 0;
    try {
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
        return i;
    }
}

Блок finally всегда выполняется, если нет аномального завершения программы, вызванного сбоем JVM или вызовом System.exit(0) .

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







try-catch-finally