Déclaration et initialisation des variables dans les commutateurs Java

j'ai une question folle sur les commutateurs Java.

int key = 2;

switch (key) {
    case 1:
        int value = 1;
        break;
    case 2:
        value = 2;
        System.out.println(value);
        break;
    default:
        break;
}

scénario 1 - lorsque le key est deux, il affiche avec succès la valeur 2.

scénario 2-Quand je vais commenter value = 2 dans case 2: il grogne en disant le la valeur de la variable locale peut ne pas avoir été initialisée .

Questions :



Scénario 1 : Si le flux d'exécution ne va pas à case 1: (quand le key = 2 ), alors comment connaît-il le type de la variable de valeur comme int ?



scénario 2: si le compilateur connaît le type de la variable de valeur comme int , alors il doit avoir accédé à l'expression int value = 1; dans case 1: .(Déclaration et Initialisation). Alors pourquoi est-ce que c'est sqawrk quand je vais commenter value = 2 dans case 2: , en disant la valeur de la variable locale peut ne pas avoir été initialisée .

86
demandé sur Mr. Polywhirl 2012-05-30 10:04:52

4 réponses

instructions de commutation sont impairs en termes de portée, dans le fond. De section 6.3 de la JLS :

la portée d'une déclaration variable locale dans un bloc (§14.4) est le reste du bloc dans lequel la déclaration apparaît, en commençant par son propre initialiseur et en incluant tout autre déclarant à droite dans la déclaration de déclaration variable locale.

Dans votre cas, case 2 est en le même bloque que case 1 et apparaît après lui, même si case 1 n'exécutera jamais... donc la variable locale est dans la portée et disponible pour écrire malgré vous logiquement jamais "l'exécution" de la déclaration. (Une déclaration n'est pas vraiment "exécutable" bien que l'initialisation.)

si vous commentez l'affectation value = 2; , le compilateur sait toujours à quelle variable vous faites référence, mais vous ne le ferez pas. ont traversé tout le chemin d'exécution qui lui attribue une valeur, c'est pourquoi vous obtenez une erreur comme vous le feriez lorsque vous essayez de lire d'autres pas-certainement attribué variable locale.

je vous recommande fortement pas d'utiliser des variables locales déclarées dans d'autres cas - cela conduit à un code très confus, comme vous l'avez vu. Lorsque j'introduis des variables locales dans les instructions de changement (ce que j'essaie de faire rarement - les cas devraient être très courts, idéalement), j'ai l'habitude préfèrent introduire une nouvelle portée:

case 1: {
    int value = 1;
    ...
    break;
}
case 2: {
    int value = 2;
    ...
    break;
}

je crois que c'est plus clair.

101
répondu Jon Skeet 2012-05-30 06:12:04

la variable a été déclarée (comme int), mais non initialisée (avec une valeur initiale). Pensez à la ligne:

int value = 1;

:

int value;
value = 1;

la partie int value indique au compilateur au moment de la compilation que vous avez une variable appelée value qui est un int. La partie value = 1 l'initialise, mais cela se produit à l'exécution, et ne se produit pas du tout si cette branche de l'interrupteur n'est pas entrée.

21
répondu Paulpro 2012-05-30 06:10:53

de http://www.coderanch.com/t/447381/java-programmer-SCJP/certification/variable-initialization-within-case-block

Les déclarations

sont traitées au moment de la compilation et ne dépendent pas de la le flux d'exécution de votre code. Depuis value est déclaré dans le local portée du bloc d'interrupteur, il est utilisable n'importe où dans ce bloc de le point de sa déclaration.

18
répondu Garbage 2012-05-30 06:10:13

grâce À l'intégration de JEP 325: Commutateur Expressions (Extrait) dans le JDK-12 early access crée. Il y a certains changements que l'on peut voir à partir de réponse de Jon -

  1. Variable locale portée - les variables locales dans les boîtiers d'interrupteurs peuvent maintenant être locales au boîtier lui-même au lieu du bloc d'interrupteurs complet . Un exemple (semblable à ce que Jon avait tenté syntaxiquement aussi bien) en considérant la classe Day enum pour une explication plus détaillée:

    public enum Day {
        MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
    }
    
    // some another method implementation
    Day day = Day.valueOf(scanner.next());
    switch (day) {
        case MONDAY,TUESDAY -> {
            var temp = "mon-tue";
            System.out.println(temp);
        }
        case WEDNESDAY,THURSDAY -> {
            var temp = Date.from(Instant.now()); // same variable name 'temp'
            System.out.println(temp);
        }
        default ->{
            var temp = 0.04; // different types as well (not mandatory ofcourse)
            System.out.println(temp);
        }
    }
    
  2. Commutateur Expressions - Si l'intention est d'affecter une valeur à une variable, puis de l'utiliser, une fois peut utiliser le commutateur expressions. par exemple

    private static void useSwitchExpression() {
        int key = 2;
        int value = switch (key) {
            case 1 ->  1;
            case 2 -> 2;
            default -> {break 0;}
        };
        System.out.println("value = " + value); // prints 'value = 2'
    }
    
1
répondu nullpointer 2018-09-08 18:55:04