Algunas de las razones ya se han señalado. Por ejemplo, el hecho de que "... (Casi) Todas las operaciones en byte, corto promoverán estas primitivas a int" . Sin embargo, la siguiente pregunta obvia sería: ¿POR QUÉ se promueven estos tipos int
?
Entonces, para ir un nivel más profundo: la respuesta simplemente puede estar relacionada con el Conjunto de instrucciones de la máquina virtual Java. Como se resume en la Tabla en la Especificación de máquina virtual Java , todas las operaciones aritméticas integrales, como sumar, dividir y otras, solo están disponibles para el tipo int
y el tipo long
, y no para los tipos más pequeños.
(Un aparte: los tipos más pequeños ( byte
y short
) básicamente están destinados solo a matrices . Una matriz como new byte[1000]
tomará 1000 bytes, y una matriz como new int[1000]
tomará 4000 bytes)
Ahora, por supuesto, uno podría decir que "... la siguiente pregunta obvia sería: ¿POR QUÉ estas instrucciones solo se ofrecen para int
(y long
)?" .
Una razón se menciona en la especificación JVM mencionada anteriormente:
Si cada instrucción escrita admitiera todos los tipos de datos de tiempo de ejecución de la máquina virtual Java, habría más instrucciones de las que podrían representarse en un byte
Además, la máquina virtual Java puede considerarse como una abstracción de un procesador real. Y la introducción de una unidad lógica aritmética dedicada para tipos más pequeños no valdría la pena: necesitaría transistores adicionales, pero aún así solo podría ejecutar una adición en un ciclo de reloj. La arquitectura dominante cuando se diseñó la JVM era de 32 bits, justo para un 32 bits int
. (Las operaciones que involucran un long
valor de 64 bits se implementan como un caso especial).
(Nota: el último párrafo está un poco simplificado, considerando la posible vectorización, etc., pero debe dar la idea básica sin profundizar demasiado en los temas de diseño del procesador)
EDITAR: Una breve adición, centrada en el ejemplo de la pregunta, pero en un sentido más general: también se podría preguntar si no sería beneficioso almacenar campos utilizando los tipos más pequeños. Por ejemplo, uno podría pensar que la memoria se podría guardar almacenando Calendar.DAY_OF_WEEK
como a byte
. Pero aquí, el formato de archivo de clase Java entra en juego: todos los campos en un archivo de clase ocupan al menos un "espacio", que tiene el tamaño de uno int
(32 bits). (Los campos "anchos" double
y long
ocupan dos espacios). Por lo tanto, declarar explícitamente un campo como short
o byte
no guardaría ninguna memoria tampoco.
int
. Si tiene una referencia a otra implementación, actualizaría la respuesta e insertaría el enlace en consecuencia.(Casi) Todas las operaciones activadas
byte
, lasshort
promocionarán aint
, por ejemplo, no puede escribir:La aritmética es más fácil y directa cuando se usa
int
, no es necesario lanzar.En términos de espacio, tiene una muy poca diferencia.
byte
yshort
complicaría las cosas, no creo que esta micro optimización valga la pena ya que estamos hablando de una cantidad fija de variables.byte
es relevante y útil cuando programa para dispositivos integrados o cuando trata con archivos / redes. Además, estas primitivas son limitadas, ¿y si los cálculos pudieran exceder sus límites en el futuro? Trate de pensar en una extensión para laCalendar
clase que pueda desarrollar números más grandes.También tenga en cuenta que en los procesadores de 64 bits, los locales se guardarán en los registros y no utilizar ningún recurso, por lo que usar
int
,short
y otras primitivas no hará ninguna diferencia en absoluto. Además, muchas implementaciones de Java alinean variables * (y objetos).*
byte
yshort
ocupan el mismo espacio comoint
si fueran variables locales , variables de clase o incluso variables de instancia . ¿Por qué? Porque en (la mayoría) de los sistemas informáticos, las direcciones de las variables están alineadas , por lo que, por ejemplo, si usa un solo byte, en realidad terminará con dos bytes, uno para la variable en sí y otro para el relleno.Por otro lado, en las matrices,
byte
tome 1 byte,short
tome 2 bytes yint
tome cuatro bytes, porque en las matrices solo el inicio y quizás el final deben estar alineados. Esto hará una diferencia en caso de que quiera usar, por ejemploSystem.arraycopy()
, entonces realmente notará una diferencia de rendimiento.fuente
Porque las operaciones aritméticas son más fáciles cuando se usan números enteros en comparación con los cortos. Suponga que las constantes realmente fueron modeladas por
short
valores. Entonces tendrías que usar la API de esta manera:Observe el casting explícito. Los valores cortos se promueven implícitamente a
int
valores cuando se usan en operaciones aritméticas. (En la pila de operandos, los cortos incluso se expresan como int.) Esto sería bastante engorroso de usar, por loint
que a menudo se prefieren los valores para las constantes.En comparación con eso, la ganancia en eficiencia de almacenamiento es mínima porque solo existe un número fijo de tales constantes. Estamos hablando de 40 constantes. Cambiar su almacenamiento de
int
ashort
te salvaría40 * 16 bit = 80 byte
. Vea esta respuesta para mayor referencia.fuente
Si utilizó la filosofía en la que las constantes integrales se almacenan en el tipo más pequeño que caben, entonces Java tendría un problema grave: cada vez que los programadores escriben código utilizando constantes integrales, deben prestar especial atención a su código para verificar si el tipo de las constantes importan, y si es así, busque el tipo en la documentación y / o haga las conversiones de tipo necesarias.
Entonces, ahora que hemos esbozado un problema grave, ¿qué beneficios podría esperar lograr con esa filosofía? No me sorprendería si el único efecto observable en el tiempo de ejecución de ese cambio fuera el tipo que obtienes cuando miras la constante hacia arriba a través de la reflexión. (y, por supuesto, los errores introducidos por programadores perezosos / involuntarios que no representan correctamente los tipos de las constantes)
Sopesar los pros y los contras es muy fácil: es una mala filosofía.
fuente
La complejidad del diseño de una máquina virtual depende de la cantidad de operaciones que puede realizar. Es más fácil tener cuatro implementaciones de una instrucción como "multiplicar", una para números enteros de 32 bits, números enteros de 64 bits, punto flotante de 32 bits y punto flotante de 64 bits, que tener, además a lo anterior, versiones para los tipos numéricos más pequeños también. Una pregunta de diseño más interesante es por qué debería haber cuatro tipos, en lugar de menos (realizar todos los cálculos de enteros con enteros de 64 bits y / o hacer todos los cálculos de punto flotante con valores de punto flotante de 64 bits). La razón para usar números enteros de 32 bits es que se esperaba que Java se ejecutara en muchas plataformas en las que los tipos de 32 bits podrían actuar tan rápido como los tipos de 16 u 8 bits, pero las operaciones en tipos de 64 bits serían notablemente más lento.solo tiene tipos de 32 bits.
En cuanto a realizar cálculos de punto flotante en valores de 32 bits, las ventajas son un poco menos claras. Hay algunas plataformas donde un cálculo como
float a=b+c+d;
podría realizarse más rápidamente al convertir todos los operandos a un tipo de mayor precisión, agregarlos y luego convertir el resultado a un número de coma flotante de 32 bits para el almacenamiento. Hay otras plataformas donde sería más eficiente realizar todos los cálculos utilizando valores de coma flotante de 32 bits. Los creadores de Java decidieron que se debería exigir a todas las plataformas que hicieran las cosas de la misma manera, y que deberían favorecer las plataformas de hardware para las cuales los cálculos de punto flotante de 32 bits son más rápidos que los más largos, a pesar de que esta PC degradó severamente la velocidad y precisión de las matemáticas de punto flotante en una PC típica, así como en muchas máquinas sin unidades de punto flotante. Tenga en cuenta, por cierto, que dependiendo de los valores de b, c y d, usar cálculos intermedios de mayor precisión al calcular expresiones como las mencionadas anteriormentefloat a=b+c+d;
a veces arrojará resultados que son significativamente más precisos que los que se obtendrían de todos los operandos intermedios que se calcularon confloat
precisión, pero a veces arrojará un valor que es un poco menos preciso. En cualquier caso, Sun decidió que todo debería hacerse de la misma manera, y optaron por usarfloat
valores de precisión mínima .Tenga en cuenta que las principales ventajas de los tipos de datos más pequeños se hacen evidentes cuando un gran número de ellos se almacenan juntos en una matriz; incluso si no hubiera ninguna ventaja de tener variables individuales de tipos más pequeños que 64 bits, vale la pena tener matrices que puedan almacenar valores más pequeños de manera más compacta; tener una variable local sea en
byte
lugar de unlong
ahorro de siete bytes; tener una matriz de 1,000,000 de números contiene cada número como un enbyte
lugar de unlong
agita 7,000,000 bytes. Dado que cada tipo de matriz solo necesita admitir algunas operaciones (especialmente leer un elemento, almacenar un elemento, copiar un rango de elementos dentro de una matriz o copiar un rango de elementos de una matriz a otra), la complejidad añadida de tener más Los tipos de matriz no son tan graves como la complejidad de tener más tipos de valores numéricos discretos directamente utilizables.fuente
En realidad, habría una pequeña ventaja. Si tienes un
luego, en una JVM típica, necesita tanto espacio como una clase que contenga una sola
int
. El consumo de memoria se redondea al siguiente múltiplo de 8 o 16 bytes (IIRC, eso es configurable), por lo que los casos en los que hay un ahorro real son bastante raros.Esta clase sería un poco más fácil de usar si los
Calendar
métodos correspondientes devolvieran abyte
. Pero no existen talesCalendar
métodos, sologet(int)
que deben devolver yint
debido a otros campos. Cada operación en tipos más pequeños promueveint
, por lo que necesita una gran cantidad de fundición.Lo más probable es que te rindas y cambies a una
int
o escribas setters comoEntonces el tipo de
DAY_OF_WEEK
no importa, de todos modos.fuente