web-dev-qa-db-fra.com

Erreur du compilateur de code inaccessible

Le code suivant donne une erreur de compilation unreachable statement

public static void main(String[] args) {
    return;
    System.out.println("unreachable");
}

Parfois, à des fins de test, si vous souhaitez empêcher l’appel d’une méthode, un moyen rapide de la faire (au lieu de la commenter partout où elle est utilisée) consiste à renvoyer immédiatement la méthode pour que la méthode ne fasse rien. Ce que je fais alors toujours pour obtenir l’erreur du compilateur est la suivante:

public static void main(String[] args) {
    if (true) {
        return;
    }
    System.out.println("unreachable");
}

Je suis juste curieux, pourquoi est-ce une erreur de compilation? Est-ce que cela va casser le bytecode Java d'une manière ou d'une autre, est-ce pour protéger le programmeur ou est-ce autre chose?

Aussi (et cela m'est plus intéressant), si compiler Java en bytecode effectue tout type d'optimisation (ou même s'il ne le fait pas), alors pourquoi ne détecte-t-il pas le code flagrant inaccessible dans le deuxième exemple? Quel serait le pseudo-code du compilateur pour vérifier si une instruction est inaccessible?

24
ughzan

Le code inaccessible n'a pas de sens, l'erreur de compilation est donc utile. La raison pour laquelle il ne sera pas détecté dans le deuxième exemple est, comme prévu, à des fins de test/débogage. C’est expliqué dans The Specification: 

if (false) { x=3; }

n'entraîne pas d'erreur de compilation. Un compilateur optimiseur peut Se rendre compte que l'instruction x = 3; ne sera jamais exécuté et peut choisir d’omettre le code pour cette instruction du fichier de classe généré, mais l’instruction x = 3; n'est pas considéré comme "inaccessible" au sens technique spécifié ici.

La raison de ce traitement différent est de permettre aux programmeurs De définir des "variables de drapeau" telles que:

static final boolean DEBUG = false;

puis écrivez un code tel que:

if (DEBUG) { x=3; }

L'idée est qu'il devrait être possible de changer la valeur de DEBUG De false en true ou de true en false, puis de compiler correctement le code Sans autre modification du texte du programme.

Référence: http://docs.Oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.21

22
André

C'est parce que l'auteur du compilateur a supposé que l'homme aux commandes est idiot, et qu'il ne voulait probablement pas ajouter de code qui ne serait jamais exécuté - donc en émettant une erreur, il tente de vous empêcher de créer par inadvertance un chemin de code exécuté - au lieu de vous forcer à prendre une décision à ce sujet (même si, comme vous l'avez prouvé, vous pouvez toujours contourner le problème).

7
jka6510

Cette erreur est principalement là pour éviter les erreurs de programmation (un échange de 2 lignes ou plus). Dans le deuxième extrait, vous expliquez clairement que vous ne vous souciez pas de system.out.println (). 

2
Guillaume Polet

Est-ce que cela va casser le bytecode Java d'une manière ou d'une autre, est-ce pour protéger le programmeur ou est-ce autre chose?

Cela n’est pas nécessaire en ce qui concerne Java/JVM. Le seul but de cette erreur de compilation est d’éviter les erreurs de programmation stupides. Considérez le code JavaScript suivant:

function f() {
    return 
        {
            answer: 42
        }
}

Cette fonction retourne undefined car le moteur JavaScript ajoute un point-virgule à la fin de la ligne et ignore le code mort (comme il le pense). Le compilateur Java est plus intelligent et quand il découvre que vous faites quelque chose clairement et manifestement dans le faux, il ne vous laissera pas faire cela. Il n'y a aucun moyen sur terre que vous vouliez avoir un code mort. Cela correspond en quelque sorte à la prémisse Java d'être un langage sûr.

2
Tomasz Nurkiewicz

http://docs.Oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.21

dit:

14.21. Déclarations inaccessibles

Il s'agit d'une erreur de compilation si une instruction ne peut pas être exécutée car elle est inaccessible.

0
Vitalii Supryhan

Dans le premier cas, vous revenez avant toute instruction à cause de cela, le compilateur n'exécutera jamais ce code. 

En deuxième code, j'ai mis la déclaration ci-dessus de retour et son travail maintenant :)

La raison derrière cela est que si vous retournez un jour, le code après qu'il ne sera jamais exécuté car vous avez déjà renvoyé les données de la fonction et affiche ainsi du code inaccessible.

public static void main (String [] args) {

return;
System.out.println("unreachable");

}

/////////////////////////////////////

public static void main (String [] args) {

System.out.println("unreachable"); // Put the statement before return
return;

}

0
Shubham Jain