Dois returns em try/finally

Qual é a lógica de execução de blocos try/catch/finally quando há "return"s envolvidos? Por exemplo: se eu uso um return no bloco try e um return no bloco finally, qual valor será devolvido? Eu queria entender o que é especificado pelo Java para este caso. Procurei no JLS e não encontrei nada específico.

O código abaixo, por exemplo, possui apenas os tais 2 returns. Quando rodado, ele incrementa o i dentro do try mas devolve o valor -1 do return do finally. Por que isso?!?!

class Finally {
        static int i = 0;
        public static void main (String args[]) {
                System.out.println(teste());
                System.out.println(i);
        }

        static int teste() {
                try {
                        return i++;
                } finally {
                        return -1;
                }
        }
}

finally sempre eh executado, mesmo qdo ha returns.

Rafael

sim, mas me parece q estão executando os 2 returns! nao?
isso me parece estranho…

…provavelmente não vai escalerecer muito, mas…

no nível do java bytecode(que é que as classes compilados contém) os blocos finally são implementados pelo java compiladores com o comando jsr http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc7.html#jsr - que executa uma sub-rotina.

O código dentro do bloco finally é a sub-rotina. E as chamadas com o comando jsr são colocados em cada saída do bloco try-catch. Assim fica garantido que o bloco finally vai sempre executar.

Agora, no seu exemplo, o que acontece é o sequinte:

  1. o valor do i está incrementado
  2. o bloco finally está sendo chamado
  3. depois o valor da i(quer dizer antes da incrementação, ou seja: 0) seria retornado, mas isso nunca acontece, porque o return no bloco finally está executado e a executação sai do metodo retornando -1.

Então só um return está executando, mas dá pra ver que a execução do bloco finally acontece realmente no último momento antes de sair do bloco try.

Talvez o sequinte esclarece um pouqinho.

class Finally {
    static int i = 0;
    public static void main(String args[]) {
        System.out.println(teste());
        System.out.println(i);
    }

    static int teste() {
        try {
            return i++;
        } finally {
            System.out.println("finally :" + Finally.i);
            return -1;
        }
    }
}

imprime:

Então… o valor do i já foi incrementado quando a execução entrou no bloco finally… mesmo que o valor(da evaluação “i++”) que o metodo pretende retornar é 0.

Faz sentido? Desculpa, fico repetindo coisas porque não quero ser mal entendido por causa do meu português imperfeito.

-Sami