1. Datilografia
Variáveis de tipos primitivos (com exceção do boolean
tipo) são usadas para armazenar vários tipos de números. Embora os tipos de variáveis nunca tenham mudado, há um lugar onde você pode converter de um tipo para outro. E esse lugar é atribuição .
Variáveis de tipos diferentes podem ser atribuídas umas às outras. Ao fazer isso, o valor de uma variável de um tipo é convertido em um valor de outro tipo e atribuído à segunda variável. Nesse sentido, podemos identificar dois tipos de conversão de tipo: alargamento e estreitamento.
Ampliar é como mover um valor de uma cesta pequena para uma grande: esta operação é contínua e indolor. O estreitamento acontece quando você move um valor de uma cesta grande para uma pequena: pode não haver espaço suficiente e você terá que jogar algo fora.
Aqui estão os tipos, classificados por tamanho da cesta:
2. Ampliando as conversões de tipo
Geralmente é necessário atribuir uma variável de um tipo numérico a uma variável de outro tipo numérico. Como você faz isso?
Java tem 4 tipos inteiros:
Tipo | Tamanho |
---|---|
byte |
1 byte |
short |
2 bytes |
int |
4 bytes |
long |
8 bytes |
Variáveis armazenadas em cestas menores sempre podem ser atribuídas a variáveis armazenadas em cestas maiores.
int
, short
e byte
variáveis podem ser facilmente atribuídas a long
variáveis. short
e byte
variáveis podem ser atribuídas a int
variáveis. E byte
variáveis podem ser atribuídas a short
variáveis.
Exemplos:
Código | Descrição |
---|---|
|
Este código irá compilar perfeitamente. |
Essa conversão, de um tipo menor para um maior, é chamada de conversão de tipo de ampliação .
E os números reais?
Com eles, tudo é igual — o tamanho importa:
Tipo | Tamanho |
---|---|
float |
4 bytes |
double |
8 bytes |
float
variáveis podem ser atribuídas a double
variáveis sem nenhum problema. Mas as coisas são mais interessantes com os tipos inteiros.
Você pode atribuir qualquer variável inteira a uma float
variável. Até mesmo o long
tipo, que tem 8 bytes de comprimento. E você pode atribuir o que quiser — qualquer variável inteira ou float
variável — a uma double
variável:
Código | Observação |
---|---|
|
|
Observe que a conversão para um tipo real pode resultar em perda de precisão devido à falta de dígitos significativos suficientes.
Ao converter de números inteiros para números de ponto flutuante, as partes de ordem inferior dos números podem ser descartadas. Mas como os números fracionários são entendidos como armazenando valores aproximados, tais operações de atribuição são permitidas.
3. Limitando as conversões de tipo
E as outras possibilidades? E se você precisar atribuir um long
valor a uma int
variável?
Imagine uma variável como uma cesta. Temos cestos de vários tamanhos: 1, 2, 4 e 8 bytes. Não é um problema transferir as maçãs de uma cesta menor para uma maior. Mas ao mudar de uma cesta maior para uma menor, algumas maçãs podem ser perdidas.
Essa transformação — de um tipo maior para um tipo menor — é chamada de conversão de tipo de restrição . Ao executar uma operação de atribuição como esta, parte de um número pode simplesmente não caber na nova variável e, portanto, pode ser descartada.
Ao restringir um tipo, devemos dizer explicitamente ao compilador que não estamos cometendo um erro, que estamos descartando deliberadamente parte do número. O operador typecast é usado para isso. É um nome de tipo entre parênteses .
Em tais situações, o compilador Java requer que o programador especifique o operador typecast. Em geral, parece com isso:
(type) expression
Exemplos:
Código | Descrição |
---|---|
|
Cada vez que o operador typecast deve ser indicado explicitamente |
Aqui a
é igual a 1
, e talvez o operador typecast pareça um exagero. Mas e se a
fossem maiores?
Código | Descrição |
---|---|
|
|
Um milhão se encaixa perfeitamente em um long
e em um int
. Mas ao atribuir um milhão a uma short
variável, os dois primeiros bytes são descartados e apenas os dois últimos bytes são retidos. E ao atribuir a um byte
, a única coisa que resta é o último byte.
Como os números são organizados na memória:
Tipo | Notação binária | Notação decimal |
---|---|---|
int |
0b 00000000 00001111 01000010 01000000 | 1000000 |
short |
0b 01000010 01000000 | 16.960 |
byte |
0b 01000000 | 64 |
char
tipo
A char
, como a short
, ocupa dois bytes, mas para converter um em outro, você sempre precisa usar um operador typecast. O problema aqui é que o short
tipo é assinado e pode conter valores de -32,768
a +32,767
, mas o char
tipo não é assinado e pode conter valores de 0
a 65,535
.
Números negativos não podem ser armazenados em a char
, mas podem ser armazenados em a short
. E a short
não pode armazenar números maiores que 32,767
, mas esses números podem ser armazenados em a char
.
4. Tipo de expressão
E se variáveis de tipos diferentes forem usadas na mesma expressão? Logicamente, entendemos que primeiro eles precisam ser convertidos para um tipo comum. Mas qual deles?
Para o maior, é claro.
Java sempre converte para o tipo maior. Grosso modo, primeiro é ampliado um do tipo e só então é realizada a operação com valores do mesmo tipo.
Se an int
e a long
estiverem envolvidos em uma expressão, o valor de the int
será convertido para a long
e só então a operação prosseguirá:
Código | Descrição |
---|---|
|
a será ampliado para a long e então a adição ocorrerá. |
Números de ponto flutuante
Se um inteiro e um número de ponto flutuante ( float
ou double
) estiverem envolvidos em uma expressão, o inteiro será convertido em um número de ponto flutuante ( float
ou double
) e somente então a operação será executada.
Se a operação envolver a float
e a double
, o float
será convertido em a double
. O que é realmente esperado.
Os tipos byte
, short
e char
são sempre convertidos em int
quando interagem entre si. Há uma boa razão pela qual o int
tipo é considerado o tipo inteiro padrão.
Se você multiplicar a byte
por a short
, obterá um int
. Se você multiplicar a byte
por a byte
, obterá um int
. Mesmo se você adicionar a byte
e a byte
, obterá um int
.
Há várias razões para isso. Exemplos:
Código | Descrição |
---|---|
|
110 * 120 é 13,200 , que é um pouco maior que o valor máximo do byte tipo:127 |
|
110 + 120 is 230 , que também é um pouco maior que o valor máximo do byte tipo:127 |
Em geral, ao multiplicar um número de 8 bits (1 byte) por um número de 8 bits (1 byte), obtemos um número que ocupa bits de 16 bits (2 bytes)
Como resultado, todas as operações com tipos inteiros menores que int
são sempre imediatamente convertidas em int
s. E isso significa que, se você quiser armazenar o resultado do cálculo em uma variável de um tipo menor que um int
, sempre precisará especificar explicitamente o operador typecast.
Exemplos:
Código | Descrição |
---|---|
|
A byte * byte expressão será umaint |
|
A byte + byte expressão será umaint |
|
A byte + int expressão será um int O literal é um int . |
5. Uma nuance importante
O operador typecast tem uma prioridade bastante alta.
Isso significa que se uma expressão contiver, por exemplo, adição e um operador typecast, o typecast será executado antes da adição.
Exemplo:
Código | Descrição |
---|---|
|
O operador typecast será aplicado apenas à a variável, que já é um byte . Este código não irá compilar. |
|
Esta é a maneira correta. |
Se você deseja converter a expressão inteira em um tipo específico, e não apenas um componente da expressão, coloque a expressão inteira entre parênteses e coloque o operador typecast na frente.
GO TO FULL VERSION