PMD
me dit
Un switch avec moins de 3 branches est inefficace, utilisez une instruction if. à la place.
Pourquoi ? Pourquoi 3 ? Comment définissent-ils l'efficacité ?
PMD
me dit
Un switch avec moins de 3 branches est inefficace, utilisez une instruction if. à la place.
Pourquoi ? Pourquoi 3 ? Comment définissent-ils l'efficacité ?
Parce qu'un switch
est compilé avec deux instructions spéciales de la JVM qui sont lookupswitch
y tableswitch
. Ils sont utiles lorsque l'on travaille avec un grand nombre de cas, mais ils entraînent une surcharge lorsque l'on n'a que quelques branches.
Un site if/else
au lieu d'être compilé dans une déclaration typique je
jne
... chaînes qui sont plus rapides mais nécessitent beaucoup plus de comparaisons lorsqu'elles sont utilisées dans une longue chaîne de branches.
Vous pouvez voir la différence en regardant le code d'octet, dans tous les cas, je ne m'inquiéterais pas de ces questions, si quelque chose peut devenir un problème, le JIT s'en occupera.
Exemple pratique :
switch (i)
{
case 1: return "Foo";
case 2: return "Baz";
case 3: return "Bar";
default: return null;
}
est compilé en :
L0
LINENUMBER 21 L0
ILOAD 1
TABLESWITCH
1: L1
2: L2
3: L3
default: L4
L1
LINENUMBER 23 L1
FRAME SAME
LDC "Foo"
ARETURN
L2
LINENUMBER 24 L2
FRAME SAME
LDC "Baz"
ARETURN
L3
LINENUMBER 25 L3
FRAME SAME
LDC "Bar"
ARETURN
L4
LINENUMBER 26 L4
FRAME SAME
ACONST_NULL
ARETURN
Alors que
if (i == 1)
return "Foo";
else if (i == 2)
return "Baz";
else if (i == 3)
return "Bar";
else
return null;
est compilé en
L0
LINENUMBER 21 L0
ILOAD 1
ICONST_1
IF_ICMPNE L1
L2
LINENUMBER 22 L2
LDC "Foo"
ARETURN
L1
LINENUMBER 23 L1
FRAME SAME
ILOAD 1
ICONST_2
IF_ICMPNE L3
L4
LINENUMBER 24 L4
LDC "Baz"
ARETURN
L3
LINENUMBER 25 L3
FRAME SAME
ILOAD 1
ICONST_3
IF_ICMPNE L5
L6
LINENUMBER 26 L6
LDC "Bar"
ARETURN
L5
LINENUMBER 28 L5
FRAME SAME
ACONST_NULL
ARETURN
Bien que l'utilisation d'un commutateur présente des gains d'efficacité mineurs par rapport à l'utilisation d'une déclaration if, ces gains sont négligeables dans la plupart des cas. Et tout analyseur de code source digne de ce nom reconnaîtrait que micro-optimisations sont secondaires à la clarté du code.
Ils disent qu'une instruction if est à la fois plus simple à lire et occupe moins de lignes de code qu'une instruction switch si le switch est sensiblement court.
De la Site web de la PMD :
Trop peu de branches pour une déclaration de commutation : Les instructions de commutation sont censées être utilisées pour supporter un comportement de branchement complexe. Il n'est pas conseillé d'utiliser un commutateur pour quelques cas seulement, car les commutateurs ne sont pas aussi faciles à comprendre que les instructions if-then. Dans ces cas, utilisez l'instructionif-then pour améliorer la lisibilité du code.
Pourquoi ça ?
Différentes séquences d'instructions sont utilisées lorsque le code est (enfin) compilé en code natif par le compilateur JIT. Un commutateur est implémenté par une séquence d'instructions natives qui effectuent un branchement indirect. (La séquence charge généralement une adresse à partir d'une table, puis effectue un branchement à cette adresse). Un if / else est implémenté comme des instructions qui évaluent la condition (probablement une instruction de comparaison) suivie d'une instruction de branchement conditionnel.
Pourquoi 3 ?
C'est une observation empirique, je suppose qu'elle est basée sur l'analyse des instructions du code natif généré et/ou sur l'évaluation comparative. (Ou peut-être pas. Pour en être absolument sûr, il faudrait demander à l'auteur ou aux auteurs de cette règle PMD comment ils ont obtenu ce chiffre).
Comment définissent-ils l'efficacité ?
Temps nécessaire à l'exécution des instructions.
Personnellement, je ne suis pas d'accord avec cette règle... ou plus précisément avec le message. Je pense qu'elle devrait dire qu'un if / else
est plus simple et plus lisible qu'un switch avec 2 cas. La question de l'efficacité est secondaire, et probablement non pertinente.
Je crois qu'il a à faire avec la manière d'un interrupteur, et un if/else compile vers le bas.
Dit qu'il faut 5 calculs pour le traitement d'une instruction switch. Dire une instruction if prend les deux calculs. Moins de 3 options de votre commutateur serait égal à 4 calculs en ifs vs 5 dans les commutateurs. Toutefois, la charge reste constante dans un switch, donc si il a 3 choix, ifs, serait de 3 * 2 traitées, contre 5 encore pour le commutateur.
Les gains réalisés lors de la recherche à des millions de calculs sont extrêmement négligeable. Son plus une question de "c'est la meilleure façon de le faire", plutôt que de tout ce qui pourrait vous affecter. Il ne serait que de le faire sur quelque chose que les cycles sur la fonction des millions de fois dans une itération.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.