Conversões Java primitivas

Conversões Java primitivas

1. Introdução

Java é uma linguagem digitada, o que significa que utiliza o conceito de tipos. Existem dois grupos de tipos distintos:

  1. tipos de dados primitivos

  2. tipos de dados abstratos.

Neste artigo, focaremos nas conversões de tipos primitivos.

2. Visão geral dos primitivos

A primeira coisa que precisamos saber é que tipo de valores podem ser usados ​​com tipos primitivos. Existem oito tipos primitivos que são:

  • byte - 8 bits e assinado

  • short - 16 bits e assinado

  • char - 16 bits e sem sinal, de modo que pode representar caracteres Unicode

  • int - 32 bits e assinado

  • long - 64 bits e assinado

  • float - 32 bits e assinado

  • double - 64 bits e assinado

  • boolean - não é numérico, pode ter apenas valorestrue oufalse

Não se pretende que seja uma discussão extensa sobre primitivos e falaremos um pouco mais sobre os detalhes deles conforme necessário durante as conversões.

3. Ampliando as conversões primitivas

Quando precisamos converter de um primitivo que é mais simples ou menor que o tipo de destino, não precisamos usar nenhuma notação especial para isso:

int myInt = 127;
long myLong = myInt;

Durante a conversão de ampliação, o valor primitivo menor é colocado sobre um contêiner maior, o que significa que todo o espaço extra, à esquerda do valor, é preenchido com zeros. Isso também pode ser usado para ir do grupo inteiro para o ponto flutuante:

float myFloat = myLong;
double myDouble = myLong;

Isso é possível porque a mudança para uma primitiva mais ampla não perde nenhuma informação.

4. Reduzindo a conversão primitiva

Às vezes, precisamos ajustar um valor maior que o tipo usado na declaração da variável. Isso pode resultar em perda de informações, pois alguns bytes terão que ser descartados.

Nesse caso, temos que expressar explicitamente que estamos cientes da situação e concordamos com isso, usando um elenco:

int myInt = (int) myDouble;
byte myByte = (byte) myInt;

5. Ampliando e reduzindo a conversão primitiva

Esta situação ocorre em avery specific case when we want to convert from a byte to a char. A primeira conversão é o alargamento debyte paraint e, a partir deint, é reduzido parachar.

Um exemplo irá esclarecer este ponto:

byte myLargeValueByte = (byte) 130;   //0b10000010 -126

A representação binária de 130 é a mesma para -126, a diferença é a interpretação do bit de sinal. Vamos agora converter debyte parachar:

char myLargeValueChar = (char) myLargeValueByte;
  //0b11111111 10000010 unsigned value
int myLargeValueInt = myLargeValueChar; //0b11111111 10000010 65410

A representação dechar é um valor Unicode, mas a conversão para umint nos mostrou um valor muito grande que tem os 8 bits mais baixos exatamente iguais a -126.

Se convertermos novamente parabyte, obteremos:

byte myOtherByte = (byte) myLargeValueInt; //0b10000010 -126

O valor original que usamos. Se todo o código estava começando comchar, os valores serão diferentes:

char myLargeValueChar2 = 130; //This is an int not a byte!
  //0b 00000000 10000010 unsigned value

int myLargeValueInt2 = myLargeValueChar2; //0b00000000 10000010  130

byte myOtherByte2 = (byte) myLargeValueInt2; //0b10000010 -126

Embora a representaçãobyte seja a mesma, que é -126, a representaçãochar nos dá dois caracteres diferentes.

6. Boxing/Unboxing Conversion

Em Java, temos uma classe Wrapper para cada tipo primitivo; essa é uma maneira inteligente de fornecer aos programadores métodos úteis de processamento, sem a sobrecarga de ter tudo como uma referência pesada a objetos. Desde o Java 1.5, a capacidade de converter automaticamente de / para um objeto primitivo em um objeto anterior e posterior foi incluída e alcançada por atribuição simples:

Integer myIntegerReference = myInt;
int myOtherInt = myIntegerReference;

7. Conversões de String

Todos os tipos primitivos podem ser convertidos emString por meio de suas classes Wrapper, que substituem o métodotoString():

String myString = myIntegerReference.toString();

Se precisarmos voltar para um tipo primitivo, precisamos usar um método de análise definido pela classe Wrapper correspondente:

byte  myNewByte   = Byte.parseByte(myString);
short myNewShort  = Short.parseShort(myString);
int   myNewInt    = Integer.parseInt(myString);
long  myNewLong   = Long.parseLong(myString);

float  myNewFloat  = Float.parseFloat(myString);
double myNewDouble = Double.parseDouble(myString);
boolean myNewBoolean = Boolean.parseBoolean(myString);

A única exceção aqui é a classeCharacter porque umString é feito dechars de qualquer maneira, desta forma, considerando que provavelmente oString é feito de um únicochar, podemos usar o métodocharAt() da classeString:

char myNewChar = myString.charAt(0);

8. Promoções Numéricas

Para executar uma operação binária, é necessário que ambos os operandos sejam compatíveis em termos de tamanho.

Há um conjunto de regras simples que se aplicam:

  1. Se um dos operandos for umdouble, o outro é promovido paradouble

  2. Caso contrário, se um dos operandos for umfloat, o outro é promovido parafloat

  3. Caso contrário, se um dos operandos for umlong, o outro é promovido paralong

  4. Caso contrário, ambos são consideradosint

Vamos ver um exemplo:

byte op1 = 4;
byte op2 = 5;
byte myResultingByte = (byte) op1 + op2;

Ambos os operandos foram promovidos paraint e o resultado deve ser reduzido parabyte novamente.

9. Conclusão

A conversão entre tipos é uma tarefa muito comum nas atividades de programação diária. There is a set of rules that govern the ways in which statically typed languages operate those conversions. Saber essas regras pode economizar muito tempo ao tentar descobrir por que um determinado código está compilando ou não.

O código usado neste artigo pode ser encontradoover on GitHub.