Por que a API Java usa int
, quando short
ou mesmo byte
seria suficiente?
Exemplo: O DAY_OF_WEEK
campo na classe Calendar
usa int
.
Se a diferença é mínima demais, por que esses tipos de dados ( short
, int
) existem?
fonte
Por que a API Java usa int
, quando short
ou mesmo byte
seria suficiente?
Exemplo: O DAY_OF_WEEK
campo na classe Calendar
usa int
.
Se a diferença é mínima demais, por que esses tipos de dados ( short
, int
) existem?
Algumas das razões já foram apontadas. Por exemplo, o fato de "... (Quase) Todas as operações no byte, curto promoverão essas primitivas para int" . No entanto, a próxima pergunta óbvia seria: POR QUE esses tipos são promovidos int
?
Então, para ir um nível mais além: a resposta pode estar simplesmente relacionada ao conjunto de instruções da Java Virtual Machine. Conforme resumido na Tabela em Java Virtual Machine Specification , todas as operações aritméticas integrais, como adição, divisão e outras, estão disponíveis apenas para o tipo int
e o tipo long
, e não para os tipos menores.
(Além disso: os tipos menores ( byte
e short
) destinam-se basicamente apenas a matrizes . Uma matriz como new byte[1000]
terá 1000 bytes e uma matriz como new int[1000]
4000 bytes)
Agora, é claro, alguém poderia dizer que "... a próxima pergunta óbvia seria: POR QUE essas instruções são oferecidas apenas para int
(e long
)?" .
Um motivo é mencionado nas especificações da JVM mencionadas acima:
Se cada instrução digitada suportasse todos os tipos de dados de tempo de execução da Java Virtual Machine, haveria mais instruções do que poderiam ser representadas em um byte
Além disso, a Java Virtual Machine pode ser considerada como uma abstração de um processador real. E a introdução da Unidade Lógica Aritmética dedicada para tipos menores não valeria o esforço: precisaria de transistores adicionais, mas ainda assim poderia executar apenas uma adição em um ciclo de clock. A arquitetura dominante quando a JVM foi projetada era de 32 bits, ideal para 32 bits int
. (As operações que envolvem um long
valor de 64 bits são implementadas como um caso especial).
(Nota: o último parágrafo é um pouco simplificado, considerando possíveis vetorizações etc., mas deve fornecer a idéia básica sem se aprofundar nos tópicos de design do processador)
EDIT: Um pequeno adendo, focado no exemplo da pergunta, mas em um sentido mais geral: também se poderia perguntar se não seria benéfico armazenar campos usando os tipos menores. Por exemplo, pode-se pensar que a memória pode ser salva armazenando Calendar.DAY_OF_WEEK
como a byte
. Mas aqui o Java Class File Format entra em jogo: Todos os campos em um arquivo de classe ocupam pelo menos um "slot", que tem o tamanho de um int
(32 bits). (Os campos "largos" double
e long
ocupam dois slots). Declarar de forma explícita um campo como short
ou byte
não guardar qualquer memória também.
int
. Se você tem uma referência a outra implementação, atualizo a resposta e insiro o link adequadamente.(Quase) Todas as operações em
byte
,short
vai promovê-los paraint
, por exemplo, você não pode escrever:A aritmética é mais fácil e direta ao usar
int
, sem necessidade de fundição.Em termos de espaço, faz uma diferença muito pequena.
byte
eshort
complicaria as coisas, não acho que essa micro otimização valha a pena, pois estamos falando de uma quantidade fixa de variáveis.byte
é relevante e útil quando você programa para dispositivos incorporados ou ao lidar com arquivos / redes. Além disso, essas primitivas são limitadas, e se os cálculos puderem exceder seus limites no futuro? Tente pensar em uma extensão para aCalendar
classe que pode evoluir em números maiores.Observe também que em processadores de 64 bits, os moradores serão guardados nos registos e não vai usar todos os recursos, portanto, usando
int
,short
e outros primitivos não fará qualquer diferença. Além disso, muitas implementações Java alinham variáveis * (e objetos).*
byte
eshort
ocupam o mesmo espaço comoint
se fossem variáveis locais , variáveis de classe ou mesmo variáveis de instância . Por quê? Como na maioria dos sistemas de computadores, os endereços das variáveis são alinhados ; por exemplo, se você usar um único byte, você terá dois bytes - um para a variável em si e outro para o preenchimento.Por outro lado, em matrizes,
byte
use 1 byte,short
2 eint
4 bytes, porque nas matrizes apenas o início e talvez o final dela devem estar alinhados. Isso fará a diferença no caso de você querer usar, por exemploSystem.arraycopy()
, e notará realmente uma diferença de desempenho.fonte
Como as operações aritméticas são mais fáceis ao usar números inteiros em comparação com curtos. Suponha que as constantes foram realmente modeladas por
short
valores. Então você teria que usar a API desta maneira:Observe a transmissão explícita. Valores curtos são implicitamente promovidos para
int
valores quando usados em operações aritméticas. (Na pilha de operandos, os shorts são expressos como ints.) Isso seria bastante complicado de usar, e é por isso que osint
valores são geralmente preferidos para constantes.Comparado a isso, o ganho em eficiência de armazenamento é mínimo, porque existe apenas um número fixo dessas constantes. Estamos falando de 40 constantes. Alterar o armazenamento de
int
para parashort
protegeria você40 * 16 bit = 80 byte
. Veja esta resposta para referência adicional.fonte
Se você usasse a filosofia em que constantes integrais são armazenadas no menor tipo em que se encaixam, o Java teria um problema sério: sempre que os programadores escrevem código usando constantes integrais, eles devem prestar muita atenção ao código para verificar se o tipo de as constantes são importantes e, se assim for, procure o tipo na documentação e / ou faça as conversões de tipo necessárias.
Então, agora que descrevemos um problema sério, que benefícios você poderia esperar obter com essa filosofia? Eu não ficaria surpreso se o único efeito observável em tempo de execução dessa alteração fosse o tipo que você obtém quando procura a constante por meio de reflexão. (e, é claro, quaisquer que sejam os erros introduzidos por programadores preguiçosos / inconscientes que não respondem corretamente aos tipos de constantes)
Pesar os prós e os contras é muito fácil: é uma filosofia ruim.
fonte
A complexidade do design de uma máquina virtual é uma função de quantos tipos de operações ela pode executar. É mais fácil ter quatro implementações de uma instrução como "multiplicar" - uma para número inteiro de 32 bits, número inteiro de 64 bits, ponto flutuante de 32 bits e ponto flutuante de 64 bits - do que ter, além disso acima, versões para os tipos numéricos menores também. Uma questão de design mais interessante é por que deveria haver quatro tipos, em vez de menos (executando todos os cálculos inteiros com números inteiros de 64 bits e / ou fazendo todos os cálculos de ponto flutuante com valores de ponto flutuante de 64 bits). A razão para o uso de números inteiros de 32 bits é que o Java era executado em muitas plataformas nas quais os tipos de 32 bits poderiam ser utilizados tão rapidamente quanto os tipos de 16 ou 8 bits, mas as operações nos tipos de 64 bits seriam visivelmente Mais devagar.tendo apenas tipos de 32 bits.
Quanto à realização de cálculos de ponto flutuante em valores de 32 bits, as vantagens são um pouco menos claras. Existem algumas plataformas em que uma computação como
float a=b+c+d;
pode ser executado mais rapidamente convertendo todos os operandos para um tipo de precisão mais alta, adicionando-os e depois convertendo o resultado em um número de ponto flutuante de 32 bits para armazenamento. Existem outras plataformas nas quais seria mais eficiente executar todos os cálculos usando valores de ponto flutuante de 32 bits. Os criadores de Java decidiram que todas as plataformas deveriam fazer as coisas da mesma maneira e que deveriam favorecer as plataformas de hardware para as quais os cálculos de ponto flutuante de 32 bits são mais rápidos que os mais longos, mesmo que esse PC severamente degradado tanto a velocidade e precisão da matemática de ponto flutuante em um PC típico, bem como em muitas máquinas sem unidades de ponto flutuante. Observe, btw, que dependendo dos valores de b, c e d, usando cálculos intermediários de maior precisão ao calcular expressões como a mencionada acimafloat a=b+c+d;
algumas vezes produz resultados significativamente mais precisos do que seria alcançado com todos os operandos intermediários calculados comfloat
precisão, mas algumas vezes produz um valor um pouco menos preciso. De qualquer forma, a Sun decidiu que tudo deveria ser feito da mesma maneira e optou por usarfloat
valores de precisão mínima .Observe que as principais vantagens de tipos de dados menores se tornam aparentes quando um grande número deles é armazenado juntos em uma matriz; mesmo que não houvesse vantagem em ter variáveis individuais de tipos menores que 64 bits, vale a pena ter matrizes que possam armazenar valores menores de maneira mais compacta; ter uma variável local em
byte
vez delong
salvar sete bytes; tendo uma matriz de 1.000.000 de números, mantenha cada número como umbyte
e não comolong
acena 7.000.000 de bytes. Como cada tipo de matriz precisa apenas suportar algumas operações (principalmente ler um item, armazenar um item, copiar um intervalo de itens dentro de uma matriz ou copiar um intervalo de itens de uma matriz para outra), a complexidade adicional de ter mais tipos de matriz não é tão grave quanto a complexidade de ter mais tipos de valores numéricos discretos diretamente utilizáveis.fonte
Na verdade, haveria uma pequena vantagem. Se você tem um
em uma JVM típica, ele precisa de tanto espaço quanto uma classe que contém uma única
int
. O consumo de memória é arredondado para um próximo múltiplo de 8 ou 16 bytes (IIRC, configurável); portanto, os casos em que há economia real são bastante raros.Essa classe seria um pouco mais fácil de usar se os
Calendar
métodos correspondentes retornassem abyte
. Mas não existemCalendar
métodos, apenas oget(int)
que deve retornar umint
por causa de outros campos. Cada operação em tipos menores promoveint
, então você precisa de muita conversão.Muito provavelmente, você desistirá e mudará para um
int
ou gravará setters comoEntão o tipo de
DAY_OF_WEEK
não importa, de qualquer maneira.fonte