Creo que, hasta cierto punto, probablemente fue una decisión arbitraria basada en el uso típico del interruptor.
Un cambio se puede implementar esencialmente de dos maneras (o en principio, una combinación): para un pequeño número de casos, o aquellos cuyos valores están ampliamente dispersos, un cambio esencialmente se convierte en el equivalente de una serie de si en una variable temporal (el valor que se enciende solo debe evaluarse una vez). Para un número moderado de casos que son más o menos consecutivos en valor, se usa una tabla de cambio (la instrucción TABLESWITCH en Java), mediante la cual la ubicación a la que saltar se busca de manera efectiva en una tabla.
Cualquiera de estos métodos podría, en principio, utilizar un valor largo en lugar de un número entero. Pero creo que probablemente fue solo una decisión práctica para equilibrar la complejidad del conjunto de instrucciones y el compilador con la necesidad real: los casos en los que realmente necesita cambiar un largo son lo suficientemente raros como para que sea aceptable tener que volver a escribir como un serie de declaraciones IF, o trabajar de alguna otra manera (si los valores largos en cuestión están muy juntos, puede en su código Java cambiar el resultado int de restar el valor más bajo).
Debido a que no implementaron las instrucciones necesarias en el código de bytes y realmente no desea escribir tantos casos, no importa cuán "listo para producción" esté su código ...
[EDITAR: extraído de los comentarios sobre esta respuesta, con algunas adiciones en el fondo]
Para ser exactos, 2³² son muchos casos y cualquier programa con un método lo suficientemente largo como para contener más de eso, ¡será absolutamente horrible! En cualquier idioma. (La función más larga que conozco en cualquier código en cualquier idioma es un poco más de 6k SLOC - sí, es un gran
switch
- y es muy difícil de manejar.) Si usted está realmente atascado con tener unalong
donde se debe tener solo unaint
o menos, entonces tienes dos alternativas reales.Utilice alguna variante sobre el tema de las funciones hash para comprimir el
long
en unint
. El más simple, solo para usar cuando tienes el tipo incorrecto, ¡es simplemente lanzar! Más útil sería hacer esto:(int) ((x&0xFFFFFFFF) ^ ((x >>> 32) & 0xFFFFFFFF))
antes de encender el resultado. También tendrá que averiguar cómo transformar los casos contra los que está probando. Pero realmente, eso sigue siendo horrible, ya que no aborda el problema real de muchos casos.
Una solución mucho mejor si está trabajando con una gran cantidad de casos es cambiar su diseño para usar un
Map<Long,Runnable>
o algo similar para que esté buscando cómo enviar un valor en particular. Esto le permite separar los casos en varios archivos, lo cual es mucho más fácil de administrar cuando el recuento de casos aumenta, aunque se vuelve más complejo organizar el registro de la gran cantidad de clases de implementación involucradas (las anotaciones pueden ayudar al permitirle crear el código de registro automáticamente).FWIW, hice esto hace muchos años (cambiamos al J2SE 1.2 recién lanzado a la mitad del proyecto) cuando construí un motor de código de bytes personalizado para simular hardware masivamente paralelo (no, reutilizar la JVM no habría sido adecuado debido a la radical diferentes modelos de valor y ejecución involucrados) y simplificó enormemente el código en relación con el gran tamaño
switch
que estaba usando la versión C del código.Para reiterar el mensaje para llevar a casa, querer
switch
en along
es una indicación de que tiene los tipos incorrectos en su programa o que está construyendo un sistema con tanta variación involucrada que debería usar clases. Es hora de repensar en cualquier caso.fuente
Map<Long,Runnable>
para resolver el problema de una manera completamente diferente. :-)switch
? Querer elegir entre un conjunto finito de tantos elementos simplemente apunta a un error en el diseño fundamental del programa. El hecho de que la gente lo solicite indica simplemente que ** se equivocaron en el diseño .long
número de filas, específicamente solo necesito 4. Este es un caso en el que me hanlong
entregado una mano que indica en qué fila se está actuando, y necesito hacer cosas diferentes según la fila. Supongo que podría lanzar a int, pero me habría facilitado la vida si pudiera haberswitch
editado en la variable. Tal como está, solo estoy usando una cadena deif
y en suelse if
lugar.long
no significa que vas a comprobar todas las posibilidades, al igual que tener unint
o unString
no significa eso tampoco. Significa que los valores que tiene, que podrían ser pocos, tienen un rango amplio . Podrías estar revisando algunos casos simples y optandodefault
por el resto. Tener que hacer turnos y lanzamientos significa que correrá el riesgo de perder datos. En pocas palabras, es una mala decisión de diseño de Java, no un problema del usuario.Porque el índice de la tabla de búsqueda debe ser de 32 bits.
fuente
switch
no es necesario implementar una tabla de búsqueda necesariamente.Un largo, en arquitecturas de 32 bits, se representa con dos palabras . Ahora, imagine lo que podría suceder si debido a una sincronización insuficiente, la ejecución de la instrucción switch observa un largo con sus 32 bits altos de una escritura y los 32 bajos de otra. Podría intentar ir a ... ¡quién sabe dónde! Básicamente en algún lugar al azar. Incluso si ambas escrituras representaran casos válidos para la declaración de cambio, su combinación divertida probablemente no conduciría ni a la primera ni a la segunda, o, lo que es peor, ¡podría conducir a otro caso válido, pero no relacionado!
Al menos con un int (o tipos menores), no importa lo mal que lo estropees, la instrucción switch leerá al menos un valor que alguien realmente escribió , en lugar de un valor "de la nada".
Por supuesto, no sé la razón real (¡han pasado más de 15 años, no he estado prestando atención tanto tiempo!), Pero si se da cuenta de lo inseguro e impredecible que podría ser tal construcción, estará de acuerdo en que esta es una duda muy buena razón para no siempre tienen un interruptor en posiciones largas (y siempre -pun intended- habrá 32 bits máquinas, eso seguirá siendo válida).
fuente
if
y el resultado sería igual de malo: resultado incorrecto ~> rama incorrecta tomada. Creación de un largoif
-else
-if
cadena en lugar de unaswitch
en realidad llevar a exactamente el mismo resultado.