Pergunta

Considerando-se este código, pode ser eu certeza absoluta que o finally bloco realiza sempre, não importa o que something() o que é?

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

Solução

Sim, finally será chamado após a execução do try ou catch blocos de código.

As únicas vezes finally não seja chamada são:

  1. Se você chamar System.exit()
  2. Se a JVM falha primeiro
  3. Se a JVM atinge um loop infinito (ou algum outro não interruptable, não-encerramento da instrução) no try ou catch bloco
  4. Se o sistema operacional forçosamente termina a JVM processo;por exemplo, kill -9 <pid> no UNIX
  5. Se o sistema host morre;por exemplo, falha de energia, erro de hardware, sistema operacional do pânico, et cetera
  6. Se o finally bloco vai ser executado por um thread daemon e todos os outros não-daemon threads sair antes finally é chamado de

Outras dicas

Exemplo de código:

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

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

Saída:

finally trumps return. 
0

Além disso, apesar da má prática, se houver uma instrução return dentro do bloco finally, ele vai trump qualquer outro retorno da regular bloco.Isto é, o bloco a seguir retornará falso:

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

Mesma coisa com gerar exceções do bloco finally.

Aqui está o oficial palavras a partir da Especificação da Linguagem Java.

14.20.2.Execução de try-finally e try-catch-finalmente

Um try declaração finally o bloco é executado pela primeira executar o try bloco.Em seguida, há uma escolha:

  • Se a execução do try bloco conclui normalmente, [...]
  • Se a execução do try bloco conclui abruptamente devido a um throw de um valor V, [...]
  • Se a execução do try bloco conclui abruptamente por qualquer outro motivo R, e , em seguida, o finally o bloco é executado.Em seguida, há uma escolha:
    • Se o bloco finally conclui normalmente, em seguida, o try instrução conclui abruptamente para razão R.
    • Se o finally bloco conclui abruptamente para razão S, e , em seguida, o try instrução conclui abruptamente para razão S (e a razão R é descartada).

A especificação para return na verdade, torna isso explícito:

JLS 14.17 A Instrução de retorno

ReturnStatement:
     return Expression(opt) ;

Um return sem instrução Expression tentativas para transferir o controle para o chamador do método ou construtor que o contém.

Um return declaração Expression tentativas para transferir o controle para o chamador do método que o contém;o valor da Expression torna-se o valor da invocação de método.

Anterior descrições dizer "tentativas para transferir o controle"ao invés de apenas "controle de transferências de"porque, se há qualquer try instruções dentro do método ou construtor, cuja try blocos de conter a return declaração, em seguida, qualquer finally as cláusulas desses try declarações será executada, a fim de, mais interno para o mais externo, antes que o controle é transferido para o chamador do método ou construtor.Abrupta conclusão de um finally cláusula pode interromper a transferência de controle iniciada por um return instrução.

Além de outras respostas, é importante ressaltar que 'finalmente' tem o direito de substituir qualquer exceção/valor retornado pelo try..catch bloco.Por exemplo, o código a seguir retorna 12:

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

Da mesma forma, o método a seguir não lança uma exceção:

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

Enquanto o método a seguir não jogá-lo:

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

Eu tentei o exemplo acima com ligeira modificação-

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.");
    }
}

O código acima saídas:

finalmente supera a de regresso.
2

Isto é porque quando return i; é executado i tem um valor de 2.Depois disso o finally o bloco é executado, onde 12 é atribuído a i e, em seguida, System.out out é executado.

Depois de executar o finally bloco a try bloco retorna 2, ao invés de retornar para 12, porque este retorno instrução não é executada novamente.

Se você depurar código no Eclipse, em seguida, você terá a sensação de que depois de executar System.out de finally bloco a return instrução de try o bloco é executado novamente.Mas este não é o caso.Ele simplesmente retorna o valor 2.

Aqui está uma elaboração de A resposta de Kevin.É importante saber que a expressão a ser devolvido é avaliada antes finally, mesmo se ele for devolvido depois.

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");
    }
}

Saída:

X
finally trumps return... sort of
0

Que é a idéia de um bloco finally.Ele permite que você certifique-se de que você fazer limpezas que poderiam ser ignorados, porque você voltar, entre outras coisas, é claro.

Finalmente é chamado independentemente do que acontece no bloco try (a menos que você chamar System.exit(int) ou a Máquina Virtual de Java chutes de fora por algum outro motivo).

Um caminho lógico para pensar sobre isso é:

  1. Código colocado em um bloco finally deve ser executado o que ocorre dentro do bloco try
  2. Assim, se o código no bloco try tenta retornar um valor ou lançar uma exceção o item é colocado 'na prateleira' até o bloco finally pode executar
  3. Porque o código do bloco finally tem (por definição), uma alta prioridade, ele pode retornar ou jogar tudo o que ele gosta.Caso em que qualquer coisa de esquerda 'na prateleira' é descartada.
  4. A única exceção a isso é se o VM é completamente desligado durante o bloco try e.g.por 'Sistema.sair'

Também um retorno no fim deite fora qualquer exceção. http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html

finalmente, sempre é executado, a menos que haja término anormal do programa (como a chamada de Sistema.exit(0)..).assim, o seu sysout será impresso

O bloco finally sempre é executado, a menos que haja término anormal do programa, seja resultante de uma falha JVM, ou a partir de uma chamada para System.exit(0).

No topo do que, qualquer valor retornado dentro do bloco finally será substituir o valor devolvido antes da execução do bloco finally, para ter o cuidado de verificar todos os pontos de saída quando usando tentar finalmente.

Não, nem sempre é um caso de exceção é// Do sistema.exit(0);antes de o bloco finally impede que, finalmente, para ser executado.

  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");
        }
    }
}

Finalmente, é sempre executado, que é o ponto inteiro, só porque ele aparece no código, após o retorno não significa que essa é a forma como é implementado.O Java runtime tem a responsabilidade de executar este código quando sair o try bloco.

Por exemplo, se você tem o seguinte:

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

O runtime irá gerar algo como isto:

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

Se uma exceção não identificada é lançada a finally bloco será executado e a exceção vai continuar a propagar.

Isso é porque você atribuído o valor de i, 12, mas não retornou o valor de i para a função.O código correto é o seguinte:

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

Porque um bloco finally sempre será chamado, a menos que você chamar System.exit() (ou o thread de falha).

A resposta é simples SIM.

ENTRADA:

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");
}

SAÍDA:

catch
finally

Sim ele será chamado.Esse é o ponto de ter um, finalmente, a palavra-chave.Se pulando para fora do bloco try/catch poderia simplesmente ignorar o bloco finally era o mesmo que colocar o Sistema.de fora.println fora o try/catch.

De forma concisa, oficial da Documentação do Java (Clique aqui), está escrito que -

Se a JVM termina enquanto o try ou catch código está sendo executado e, em seguida, o bloco finally não pode executar.Da mesma forma, se o thread de execução o try ou catch código é interrompido ou morto, o bloco finally pode não execute o mesmo que o aplicativo como um todo continua.

Sim, o bloco finally é sempre executado.A maioria de uso do desenvolvedor do bloco a de fechar a conexão de banco de dados, objeto resultset, declaração de objeto e também usa para o java, hibernate para reverter a transação.

Sim, ele vai.Não importa o que acontece no seu try ou catch bloco, a menos que de outra forma de Sistema.exit() chamado ou JVM caiu.se não houver qualquer instrução return no bloco(s),finalmente vai ser executado antes de que a instrução de retorno.

Sim Ele.Apenas caso não é JVM sai ou falha

Considere o seguinte programa:

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());
        System.out.println("---PRINT THE RESULT---");
        System.out.println(sb.toString());
    }

    private static String someString() {

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

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

Como de Java 1.8.162, acima bloco de código fornece a seguinte saída:

-abc-
---AGAIN---
-abc-xyz-abc-
---PRINT THE RESULT---
-abc-xyz-abc-xyz

isto significa que, usando finally para liberar objetos é uma boa prática, como o código a seguir:

private static String someString() {

    StringBuilder sb = new StringBuilder();

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

    } finally {
        sb = null; // Just an example, but you can close streams or DB connections this way.
    }
}

Isto é uma verdade em qualquer idioma...finally sempre será executado antes de uma instrução de retorno, não importa onde o retorno é no corpo do método.Se esse não era o caso, o bloco finally não teria muito significado.

finally irá executar e que é, com certeza.

finally não será executado em casos abaixo:

caso 1 :

Quando você está executando System.exit().

caso 2 :

Quando a sua JVM / Thread falha.

caso 3 :

Quando sua execução é interrompida entre manualmente.

Se você não tratar de exceção, antes de encerrar o programa, a JVM executa bloco finally.Ele não será executado somente se a execução normal do programa irá falhar significa o término do programa, devido às seguintes razões..

  1. Por causar um erro fatal que faz com que o processo de anulação.

  2. Término do programa devido à memória corrompido.

  3. Chamando Sistema.exit()

  4. Se o programa entra em loop infinito.

Sim, porque nenhuma declaração de controle de pode impedir finally de ser executada.

Aqui é uma referência exemplo, onde todos os blocos de código será executado:

| x | Current result | Code 
|---|----------------|------ - - -
|   |                |     
|   |                | public static int finallyTest() {
| 3 |                |     int x = 3;
|   |                |     try {
|   |                |        try {
| 4 |                |             x++;
| 4 | return 4       |             return x;
|   |                |         } finally {
| 3 |                |             x--;
| 3 | throw          |             throw new RuntimeException("Ahh!");
|   |                |         }
|   |                |     } catch (RuntimeException e) {
| 4 | return 4       |         return ++x;
|   |                |     } finally {
| 3 |                |         x--;
|   |                |     }
|   |                | }
|   |                |
|---|----------------|------ - - -
|   | Result: 4      |

Na variante abaixo, return x; será ignorado.O resultado é ainda 4:

public static int finallyTest() {
    int x = 3;
    try {
        try {
            x++;
            if (true) throw new RuntimeException("Ahh!");
            return x; // skipped
        } finally {
            x--;
        }
    } catch (RuntimeException e) {
        return ++x;
    } finally {
        x--;
    }
}

Referências, é claro, de acompanhar o seu status.Este exemplo retorna uma referência com value = 4:

static class IntRef { public int value; }
public static IntRef finallyTest() {
    IntRef x = new IntRef();
    x.value = 3;
    try {
        return x;
    } finally {
        x.value++; // will be tracked even after return
    }
}

try- catch- finally são as palavras chave para o uso de manipulação de exceção do caso.
Como normal explanotory

try {
     //code statements
     //exception thrown here
     //lines not reached if exception thrown
} catch (Exception e) {
    //lines reached only when exception is thrown
} finally {
    // always executed when the try block is exited
    //independent of an exception thrown or not
}

O bloco finally impedir a execução de...

  • Quando chamado System.exit(0);
  • Se uma JVM termina.
  • Erros na JVM

Adicionar a @vibhash resposta como nenhuma outra resposta explica o que acontece no caso de um objeto mutável como a abaixo.

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

public static StringBuffer test() {
    StringBuffer s = new StringBuffer();
    try {
        s.append("sb");
        return s;
    } finally {
        s.append("updated ");
    }
}

Saída

sbupdated 

Eu tentei isso, Ele é único thread.

class Test {
    public static void main(String args[]) throws Exception {
       Object obj = new Object();
       try {
            synchronized (obj) {
            obj.wait();
            System.out.println("after wait()");
           }
       } catch (Exception e) {
       } finally {
           System.out.println("finally");
       }
   }
}

O thread principal será em estado de espera para sempre, daí, finalmente, nunca vai ser chamado,

assim, a saída do console não vai seqüência de impressão: after wait() ou finally

Concordou com @Stephen C, o exemplo acima é um dos 3º caso mencionar aqui:

A adição de mais alguns, tais loop infinito de possibilidades no código a seguir:

// import java.util.concurrent.Semaphore;
class Test {
    public static void main(String[] args) {
        try {
            // Thread.sleep(Long.MAX_VALUE);
            // Thread.currentThread().join();
            // new Semaphore(0).acquire();
            // while (true){}
            System.out.println("after sleep join semaphore exit infinite while loop");
        } catch (Exception e) {
        } finally {
            System.out.println("finally");
        }
    }
}

Caso 2:Se a JVM falha primeiro

import sun.misc.Unsafe;
import java.lang.reflect.Field;
class Test {
    public static void main(String args[]) {
        try {
            unsafeMethod();
//            Runtime.getRuntime().halt(123);
            System.out.println("After Jvm Crash!");
        } catch (Exception e) {
        } finally {
            System.out.println("finally");
        }
    }

    private static void unsafeMethod() throws NoSuchFieldException, IllegalAccessException {
        Field f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe unsafe = (Unsafe) f.get(null);
        unsafe.putAddress(0, 0);
    }
}

Ref: Como você se falhar uma JVM?

Caso 6:Se, finalmente, o bloco vai ser executado pela thread daemon e todos os outros não-daemon threads saída antes que finalmente é chamado.

class Test {
    public static void main(String args[]) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    printThreads("Daemon Thread printing");
                    // just to ensure this thread will live longer than main thread
                    Thread.sleep(10000);
                } catch (Exception e) {
                } finally {
                    System.out.println("finally");
                }
            }
        };
        Thread daemonThread = new Thread(runnable);
        daemonThread.setDaemon(Boolean.TRUE);
        daemonThread.setName("My Daemon Thread");
        daemonThread.start();
        printThreads("main Thread Printing");
    }

    private static synchronized void printThreads(String str) {
        System.out.println(str);
        int threadCount = 0;
        Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
        for (Thread t : threadSet) {
            if (t.getThreadGroup() == Thread.currentThread().getThreadGroup()) {
                System.out.println("Thread :" + t + ":" + "state:" + t.getState());
                ++threadCount;
            }
        }
        System.out.println("Thread count started by Main thread:" + threadCount);
        System.out.println("-------------------------------------------------");
    }
}

saída:Isso não imprimir "finalmente", que implica "Finalmente" bloco em "linha do daemon" não foi executada

main Thread Printing  
Thread :Thread[My Daemon Thread,5,main]:state:BLOCKED  
Thread :Thread[main,5,main]:state:RUNNABLE  
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE   
Thread count started by Main thread:3  
-------------------------------------------------  
Daemon Thread printing  
Thread :Thread[My Daemon Thread,5,main]:state:RUNNABLE  
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE  
Thread count started by Main thread:2  
-------------------------------------------------  

Process finished with exit code 0
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top