Pourquoi l'instruction de casse de commutateur dans Java prend seulement entier, court, octet et caractère seulement et pas d'autres types de données? Quel pourrait être le bénéfice? S'il vous plaît expliquer en détail.Pourquoi l'instruction switchcase dans Java fonctionne comme ceci?
Répondre
Habituellement, les questions de conception de langage se résument à "parce que c'est ainsi que les concepteurs ont décidé de le faire." C'est juste un autre de ces moments. Mais Java a quelques origines en C, qui ont fait la même chose, et dans les années 80 cette décision m'a été expliquée comme étant parce que le compilateur pouvait alors transformer le commutateur en une table de saut: Fondamentalement, chaque bloc d'adresse de code est placé dans une table et le switch
devient une vérification de plage suivie d'une recherche de table (généralement indexée dans un tableau ou au moins une liste chaînée de tableaux) en utilisant la valeur que vous passez pour obtenir l'adresse, puis passez à cette adresse. Seuls les entiers ont un sens dans ce scénario. Rappelez-vous que les ordinateurs n'étaient pas toujours aussi rapides qu'ils le sont maintenant. C a été conçu au début des années 70 sur la base du travail de la fin des années 60, lorsque les ordinateurs étaient beaucoup plus lents.
Certaines langues dans la même tradition syntaxique que Java et C, tels que JavaScript, faire le switch
juste une autre façon d'écrire if...else/if...else
et ne limite pas le type en cours de vérification à des types entiers, peut-être parce que, étant conçu les années 90, cela est devenu une option réaliste. Ou peut-être juste parce que le concepteur de JavaScript (Brendan Eich) l'a préféré de cette façon.
Ci-dessous, Baadshah demande:
Par curiosité: Alors maintenant comment ses cordes de soutien ??? Pouvez-vous s'il vous plaît donner une idée?
D'abord, un peu de recul et de regarder le int
cas:
num = Integer.parseInt(args[0]);
switch (num) {
case 1:
System.out.println("You used the special value one");
break;
case 42:
System.out.println("You used the special value forty-two");
break;
case 67:
System.out.println("You used the special value sixty-seven");
break;
default:
System.out.println("You used the a non-special value " + num);
break;
}
Ce produit bytecode comme ceci:
19: iload_2 20: lookupswitch { // 3 1: 56 42: 67 67: 78 default: 89 } 56: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 59: ldc #9 // String You used the special value one 61: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 64: goto 114 67: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 70: ldc #11 // String You used the special value forty-two 72: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 75: goto 114 78: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 81: ldc #12 // String You used the special value sixty-seven 83: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 86: goto 114 89: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 92: new #13 // class java/lang/StringBuilder 95: dup 96: invokespecial #14 // Method java/lang/StringBuilder."":()V 99: ldc #15 // String You used the a non-special value 101: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 104: iload_2 105: invokevirtual #17 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 108: invokevirtual #18 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 111: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
Nous pouvons voir la table de consultation sur la int
en action.
Alors, comment faites-vous cela avec des chaînes? Eh bien, une réponse serait de simplement transformer le switch
en une structure if...else if...else
. Mais ils ont fait quelque chose de plus intelligent que: Ils ont utilisé le hashcode pour optimiser, puis utilisés equals
pour protéger contre les collisions:
switch (str) {
case "abc":
System.out.println("You used the special value 'abc'");
break;
case "def":
System.out.println("You used the special value 'def'");
break;
case "ghi":
System.out.println("You used the special value 'ghi'");
break;
default:
System.out.println("You used the a non-special value '" + str + "'");
break;
}
devient:
124: aload 4 126: invokevirtual #19 // Method java/lang/String.hashCode:()I 129: lookupswitch { // 3 96354: 164 99333: 180 102312: 196 default: 209 } 164: aload 4 166: ldc #20 // String abc 168: invokevirtual #21 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 171: ifeq 209 174: iconst_0 175: istore 5 177: goto 209 180: aload 4 182: ldc #22 // String def 184: invokevirtual #21 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 187: ifeq 209 190: iconst_1 191: istore 5 193: goto 209 196: aload 4 198: ldc #23 // String ghi 200: invokevirtual #21 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 203: ifeq 209 206: iconst_2 207: istore 5 209: iload 5 211: tableswitch { // 0 to 2 0: 236 1: 247 2: 258 default: 269 } 236: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 239: ldc #24 // String You used the special value 'abc' 241: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 244: goto 299 247: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 250: ldc #25 // String You used the special value 'def' 252: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 255: goto 299 258: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 261: ldc #26 // String You used the special value 'ghi' 263: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 266: goto 299 269: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 272: new #13 // class java/lang/StringBuilder 275: dup 276: invokespecial #14 // Method java/lang/StringBuilder."":()V 279: ldc #27 // String You used the a non-special value ' 281: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 284: aload_3 285: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 288: ldc #28 // String ' 290: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 293: invokevirtual #18 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 296: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
Voir ce qu'ils ont fait là-bas? Il s'agit essentiellement de deux switches
maintenant: Un pour obtenir un nombre unique pour chaque cas basé sur le code de hachage (mais double vérification avec equals
), puis le second à expédier.
Par curiosité: Alors maintenant, comment son soutien Strings ??? Pouvez-vous s'il vous plaît donner une idée? –
@Baadshah: Une très bonne question! J'ai mis à jour pour y remédier. –
Merci Crowder.Awsome explication pour un commentaire simple. –
L'instruction JDK6 a fonctionné sur les types de données char, octet, int primitive et enum. Dans JDK 7, ils ont réalisé que java.lang.String est également une constante et a été ajoutée à la liste des types de données supportés par une instruction switch.
Par exemple, le code suivant fonctionne correctement dans JDK7.
public static void OpenSource(String language)
{
switch (language) {
case "PERL":
System.out.println("PERL");
break;
case "Python":
System.out.println("Python");
break;
case "Ruby":
System.out.println("Ruby");
break;
case "PHP":
System.out.println("PHP");
break;
default:
throw new IllegalArgumentException();
}
}
- 1. pourquoi java permet ceci?
- 2. pourquoi angularjs ng-include ne fonctionne pas comme ceci
- 3. "ceci" ne fonctionne pas comme prévu
- 4. Pourquoi ajouter une méthode au type de référence JavaScript comme ceci ne fonctionne pas?
- 5. Comment rediriger comme ceci
- 6. Analyser XML comme ceci
- 7. Pourquoi le clavier en mode Paysage apparaît-il comme ceci?
- 8. pourquoi la séquence du dictionnaire de swift2.0 comme ceci?
- 9. Javascript: passer "ceci" comme objet "dom", pas "ceci" comme "ceci" fonction
- 10. Loader comme ceci avec jQuery
- 11. pourquoi cette java regex ne fonctionne pas comme je veux?
- 12. ViewScoped fonctionne comme RequestScoped - pourquoi?
- 13. Java: Comment rendre ceci sérialisable?
- 14. Comment obtenir TextField comme ceci
- 15. Angulaire 2 SwitchCase avec Fade In
- 16. Déduction de "ceci" en Java?
- 17. Pourquoi Eclipse ne fonctionne pas comme Spark?
- 18. jQuery ne fonctionne pas comme prévu, pourquoi?
- 19. comment utiliser l'attribut write dans switchcase doit être un entier
- 20. Java ceci et les génériques?
- 21. Pourquoi "ceci" est-il capturé dans une fermeture?
- 22. Pourquoi getparent() ne fonctionne pas comme prévu?
- 23. Pourquoi ne pas sélectionner les variables de la liste comme ceci dans VBA?
- 24. [], je reçois ceci comme une réponse json
- 25. Comment faire une listbox/listview comme ceci
- 26. Pourquoi .on() Ne fonctionne pas comme prévu dans jquery?
- 27. Javascript ne fonctionne pas comme prévu, pourquoi?
- 28. Pourquoi ostream_iterator ne fonctionne pas comme prévu?
- 29. C++ en utilisant « ceci » comme paramètre
- 30. Pourquoi la référence Java ne fonctionne pas comme prévu dans ce programme
Il accepte également des chaînes et énumérations depuis 1.7 JDK. –
Ceci est une exigence de langue. Sous Java 7, il supporte maintenant 'String' et depuis que' enum' a été introduit, il supporte aussi 'enum'. La question se résume à comment définiriez-vous un cas pour un objet arbitraire? – MadProgrammer
@MadProgrammer Eh bien, vous pouvez créer un objet arbitraire et utiliser égal pour correspondre à chaque cas je suppose. – Thihara