web-dev-qa-db-fra.com

Code inaccessible fonctionne bien - Comment?

D'après ce que j'ai compris, le code suivant que j'ai écrit ne devrait pas être compilé, car l'instruction "Je suis inaccessible" se trouve après le return.

Cependant, la compilation est absolument parfaite.

Également du JLS: Instructions inaccessibles il ne devrait pas compiler.

de la spécification, à 14h21 Déclarations inaccessibles:

Une instruction try peut se terminer normalement si les deux conditions suivantes sont vraies:

  • Le bloc try peut se terminer normalement ou tout bloc catch peut se terminer normalement.

  • Si l'instruction try a un bloc finally, alors le bloc finally peut se terminer normalement.

Ici le bloc try ne peut pas se terminer normalement, mais le bloc catch peut aussi bien que le bloc finally, je suis donc confus ici

    public class Test1 {
     public static void main(String[] args) {
        try {
            return;

        } catch (Exception e) {
            System.out.println("catch");

        } finally {
            System.out.println("finally");
        }
        System.out.println("I am unreachable??!!!");
    }
}

Est-ce que quelqu'un peut m'aider à comprendre ce comportement?

57
Joker

Je crois que ce sont les citations pertinentes de JLS 14.21 :

  • Un bloc vide qui n'est pas un bloc de commutation peut être terminé normalement s'il est accessible.

    Un bloc non vide qui n'est pas un bloc de commutateur peut se terminer normalement si la dernière instruction qu'il contient peut se terminer normalement.

    La première instruction d'un bloc non vide qui n'est pas un bloc de commutateur est accessible si le bloc est accessible.

    Toute autre instruction S d'un bloc non vide qui n'est pas un bloc de commutateur est accessible si et seulement si l'instruction précédente est capable de se terminer normalement .

Donc votre

System.out.println("I am unreachable??!!!");

si l'instruction est accessible si et seulement si (cela signifie "si et seulement si"), l'instruction try peut se terminer normalement, ce qui conduit à la citation suivante:

  • Une instruction try peut se terminer normalement si et seulement si les deux affirmations suivantes sont vraies :

    • Le bloc try peut se terminer normalement ou tout bloc catch peut se terminer normalement .

    • Si l'instruction try a un bloc finally, alors le bloc finally peut se terminer normalement .

Puisque votre bloc catch peut se terminer normalement et , vous avez un bloc finally pouvant se terminer normalement, le try déclaration peut se terminer normalement. Par conséquent, l'instruction System.out.println("I am unreachable??!!!"); suivante est réputée accessible, indépendamment de l'instruction return; à l'intérieur du bloc try.

Notez le or dans

Le bloc try peut se terminer normalement ou tout bloc catch peut se terminer normalement.

Cela nécessite soit le bloc try ou au moins un des blocs catch pour se terminer normalement. Les blocs try et catch ne sont pas nécessaires pour se terminer normalement.

Enfin, la logique derrière ce comportement:

Le compilateur n'est pas censé analyser si un bloc try peut ou non lancer un Exception. La raison en est que la hiérarchie de classes Exception inclut les exceptions cochées et non contrôlées, et que les exceptions non contrôlées ne sont pas déclarées dans les clauses throws (si vous avez remplacé Exception par une exception vérifiée, telle que IOException, le compilateur se plaindra que votre bloc try ne lève jamais cette exception, ce qui rendrait le bloc catch inaccessible).

Par conséquent, étant donné que vous avez un bloc catch (Exception e) qui peut se terminer normalement, le compilateur suppose que ce bloc est accessible et que l'instruction try complète peut donc se terminer normalement, même si le bloc try ne peut pas se terminer normalement.

Le bloc finally, s'il est présent, doit également pouvoir se terminer normalement, car le bloc finally est également exécuté. Par conséquent, s'il ne peut pas se terminer normalement, l'instruction try complète ne peut pas se terminer normalement.

71
Eran

Vous avez le retour à essayer.

Que se passe-t-il s'il y a une exception et que cela va directement à la pêche? Par conséquent, il n'est pas inaccessible en termes de compilateur et compile avec succès.

La compilation échouera si vous avez également un retour en capture

En outre, conformément à JLS 14.21 :

Une instruction break accessible quitte une instruction si, dans la cible break, il n'y a aucune instruction try dont les blocs try contiennent l'instruction break, ou s'il existe des instructions try dont les blocs try contiennent l'instruction break et que toutes les clauses finally de ces instructions try peuvent compléter. normalement.

Voir la sortie ci-dessous lorsque vous revenez à la fois essayez et attrapez:

jshell>  public class Test1 {
   ...>     public static void main(String[] args) {
   ...>         try {
   ...>             return;
   ...>
   ...>         } catch (Exception e) {
   ...>             return;
   ...>
   ...>         }
   ...>
   ...>         System.out.println("I am unreachable??!!!");
   ...>     }
   ...> }
|  Error:
|  unreachable statement
|          System.out.println("I am unreachable??!!!");
|          ^------------------------------------------^

Le même sera le cas lorsque vous aurez à nouveau votre déclaration finale et que la compilation échouera.

Une déclaration après tentative sera considérée comme accessible si:

1) Try has a return statement with catch and finally not having return statement
2) Try does not have a return statement with catch having or not having return statement and finally not having return statement
3) Try, catch and finally not having return statement
15
Aman Chhabra

Si l’on essaie de donner une raison plus simple au problème, le code est accessible, au cas où une exception se produirait dans le bloc try. Dans ce cas, le contrôle va ensuite à catch block puis au block final. Après le blocage final, l'instruction sera exécutée.

try {
            return;                                 //line 1

        } catch (Exception e) {
            System.out.println("catch");            //line 2

        } finally {
            System.out.println("finally");          //line 3
        }
        System.out.println("I am unreachable??!!"); //line 4

Cela signifie qu'il y a 2 cas, donc 2 flux:

  1. ligne 1 -> ligne 3 -> retour (s'il n'y a pas d'exception)
  2. ligne 1 (une exception se produit) -> ligne 2 -> ligne 3 -> ligne 4 (dans le cas où try obtient une exception)

La ligne deviendra inaccessible, seulement si nous ne laissons aucune possibilité dans laquelle le contrôle va là-bas. Il y a 2 façons pour cela:

  1. retour du bloc de capture
  2. revenir de bloquer enfin.

Dans les deux cas, le contrôle ne peut jamais passer à cette ligne.

try {
            return;                                 //line 1

        } catch (Exception e) {
            System.out.println("catch");            //line 2
            return;                                 //return control
        } finally {
            System.out.println("finally");          //line 3
            return;                                 //or return from here
        }
        System.out.println("I am unreachable??!!"); //line 4    

J'espère maintenant que cela donne une image claire de la raison réelle du problème.

10
Yashi Srivastava

Lorsque vous examinez les "instructions inaccessibles" dans un programme Java, ce qui compte est ce que dit la définition dans le langage, et non ce qu'un compilateur intelligent pourrait découvrir.

Selon le langage Java, le dernier println n'est pas une instruction inaccessible. Même si, en regardant le code, il est facile (pour un homme intelligent) de comprendre qu'il ne peut jamais être exécuté.

Un langage de programmation doit s'appuyer sur des règles fixes que le compilateur peut suivre facilement. Un compilateur ne peut pas compter sur l'intelligence, car différents compilateurs auraient différentes astuces. Par conséquent, s'ils ne suivaient pas les règles simples et fixes, certains compilateurs trouveraient l'énoncé inaccessible et d'autres non.

4
gnasher729