Code inaccessible fonctionne bien – Comment?

D’après ce que j’ai compris, le code que j’ai écrit ne doit pas être compilé car la déclaration “Je suis inaccessible” est postérieure au return .

Cependant, la compilation est absolument parfaite.

Aussi à partir des instructions JLS: Unreachable, il ne doit pas être compilé.

à partir de la spécification, à 14.21 Déclarations inaccessibles:

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

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

  • Si l’instruction try a un bloc finally, 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, donc je suis confus ici

  public class Test1 { public static void main(Ssortingng[] 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?

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

  • Un bloc vide qui n’est pas un bloc de commutation peut terminer normalement s’il est accessible.

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

    La première instruction dans un bloc non vide qui n’est pas un bloc de commutation est accessible si le bloc est accessible.

    Toute autre instruction S dans un bloc non vide qui n’est pas un bloc de commutation est accessible si l’instruction précédant S peut se terminer normalement .

Donc votre

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

instruction est joignable iff (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 les deux suivantes ne sont pas vraies :

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

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

Puisque votre bloc catch peut se terminer normalement et que vous avez un bloc finally qui peut se terminer normalement, l’instruction try peut se terminer normalement. D’où le System.out.println("I am unreachable??!!!"); déclaration qui suit est réputée accessible, quel que soit le return; déclaration à l’intérieur du bloc try .

Noter le or dans

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

Cela nécessite que le bloc try ou au moins un des blocs catch se termine normalement. Il ne nécessite pas que le bloc try et le bloc catch se terminent normalement.

Enfin, la logique derrière ce comportement:

Le compilateur n’est pas censé parsingr si un bloc try peut ou non lancer une Exception . La raison en est que la hiérarchie de classes Exception comprend à la fois les exceptions cochées et non vérifiées, et que les exceptions non vérifié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 , ce qui rendrait le bloc de catch inaccessible).

Par conséquent, comme vous avez un bloc catch (Exception e) qui peut se terminer normalement, le compilateur suppose que ce catch le bloque, et par conséquent l’intégralité de l’instruction try peut 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, puisque le bloc finally est également exécuté. Par conséquent, si l’instruction ne pouvait pas se terminer normalement, l’intégralité de l’instruction try ne pourrait pas se terminer normalement.

Vous avez un retour en essai.

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 comstack avec succès.

La compilation échouera si vous avez aussi un retour dans la prise

Aussi, selon JLS 14.21 :

Une instruction break accessible permet de quitter une instruction si, à l’intérieur de la cible break, il n’ya pas d’instruction try dont les blocs try contiennent l’instruction break ou si les blocs try contiennent l’instruction break normalement.

Voir la sortie ci-dessous lorsque vous êtes de retour dans try and catch:

 jshell> public class Test1 { ...> public static void main(Ssortingng[] 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 de retour dans votre instruction finally et que la compilation échouera.

Une déclaration post-essai 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 

En essayant de donner une raison plus simplifiée pour le problème, le code est accessible, au cas où une exception se produirait dans le bloc try. Dans ce cas, le contrôle va plus loin que le bloc catch, puis le bloc finally. Après enfin bloc, l’instruction particulière 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 stream:

  1. ligne 1 -> ligne 3 -> retour (au cas où il n’y aurait 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é de contrôle. Il y a 2 façons pour cela:

  1. retour du bloc catch
  2. retour de bloc enfin.

Dans les deux cas, le contrôle ne peut jamais atteindre 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 que maintenant cela donne une image claire de la raison réelle du problème.

Lorsque vous regardez des “instructions inaccessibles” dans un programme Java, ce qui compte, c’est ce que dit la définition dans le langage, et non ce qu’un compilateur intelligent pourrait découvrir.

Selon le langage Java, la dernière impression n’est pas une instruction inaccessible. Même si en regardant le code, il est facile (pour un humain intelligent) de comprendre qu’il ne peut jamais être exécuté.

Un langage de programmation doit s’appuyer sur des règles fixes faciles à suivre pour le compilateur. Un compilateur ne peut pas compter sur l’intelligence, car différents compilateurs auraient des capacités différentes, donc, s’ils ne suivaient pas les règles simples et fixes, certains compilateurs trouveraient cette instruction inaccessible et d’autres non.