web-dev-qa-db-fra.com

Clarification d'essayer-attraper-enfin-retourner

En lisant toutes les questions déjà posées dans ce forum en relation avec le sujet ci-dessus (voir le titre), je comprends parfaitement que finally soit toujours appelé. (à l'exception de System.exit et boucles infinies). Cependant, j'aimerais savoir si un return est appelé dans un bloc catch, puis un autre return est appelé à partir du bloc finally.

Par exemple:

public static void main(String[]args) {
    int a = new TestClass().absorbeTheValue();
}

int absorbeTheValue() {
    try {
        int a = 10/0;
        if (a > 0) return 4;
    } catch(Exception e) {
        return 45;
    } finally {
        return 34;
    }
}    

Donc ici la sortie (quand la méthode est appelée) va être 34 dans tous les cas. Cela signifie que finalement toujours toujours couru. Je pense cependant que les autres "retours" ne sont pas courus du tout. Dans de nombreux articles, j’ai trouvé le fait que, finalement, écrivez le contenu par-dessus ce qui avait déjà été écrit par le retour de la clause de capture. D'après ce que j'ai compris, dès que la valeur de retour dans la clause catch est sur le point d'être évaluée, le flux de contrôle passe à la clause finally qui, à son tour, comporte un autre retour. Cette fois, le retour sera évalué sans passer le contrôle à la clause catch. . De cette façon, le seul return appelé au moment de l'exécution sera le retour final. Êtes-vous d'accord avec cela?

Un return dans finally ne renvoie pas le contrôle au programme mais renvoie la valeur et termine la méthode. Pouvons-nous le dire?

59
Rollerball

Si le return du bloc try est atteint, il transfère le contrôle au bloc finally et la fonction retourne normalement (pas une projection).

Si une exception se produit mais que le code atteint un return à partir du bloc catch, le contrôle est transféré au bloc finally et la fonction retourne finalement normalement (pas une projection). .

Dans votre exemple, vous avez return dans finally, et donc, peu importe ce qui se passe, la fonction retournera 34, parce que finally a le dernier mot (si vous voulez).

Bien que cela ne soit pas couvert dans votre exemple, cela serait vrai même si vous n'aviez pas catch et si une exception était levée dans le bloc try et not capturé . En faisant un return à partir du bloc finally, vous supprimez entièrement l'exception. Considérer:

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

  private static int foo(String[] args) {
    try {
      int n = Integer.parseInt(args[0]);
      return n;
    }
    finally {
      return 42;
    }
  }
}

Si vous exécutez cela sans fournir d'arguments:

$ Java FinallyReturn

... le code dans foo jette un ArrayIndexOutOfBoundsException. Mais comme le bloc finally effectue un return, cette exception est supprimée.

C'est l'une des raisons pour lesquelles il est préférable d'éviter d'utiliser return dans finally.

97
T.J. Crowder

Voici un code qui montre comment cela fonctionne.

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

    public static String test()
    {
        try {
            System.out.println("try");
            throw new Exception();
        } catch(Exception e) {
            System.out.println("catch");
            return "return"; 
        } finally {  
            System.out.println("finally");
            return "return in finally"; 
        }
    }
}

Le résultat est:

try
catch
finally
return in finally
70
andre