Tipos de Dados em Java

Guia completo sobre tipos primitivos, Strings, conversões e type casting em Java

1. O Básico: Entendendo Tipos de Dados

Em Java, cada variável precisa ter um tipo definido. O tipo determina que tipo de valor a variável pode armazenar, quanto espaço ela ocupa na memória e quais operações podem ser realizadas com ela.

Imagine os tipos de dados como diferentes tamanhos de caixas em um depósito. Uma caixa pequena (byte) serve para guardar números pequenos e economiza espaço. Uma caixa grande (long) pode guardar números enormes, mas ocupa mais espaço. Escolher o tipo certo significa usar o espaço de forma eficiente.

Java é uma linguagem fortemente tipada, o que significa que você deve declarar o tipo de cada variável antes de usá-la. Isso ajuda a prevenir erros e torna o código mais seguro e previsível.

2. Tipos Primitivos em Java

Java possui 8 tipos primitivos fundamentais. Eles são chamados de primitivos porque são os blocos básicos de construção da linguagem e não são objetos.

2.1. Tipos Numéricos Inteiros

byte

Tamanho: 8 bits (1 byte)

Intervalo: -128 a 127

Uso: Economizar memória em arrays grandes, trabalhar com dados binários

java
byte idade = 25;
byte temperatura = -10;
byte nivelBateria = 100;

short

Tamanho: 16 bits (2 bytes)

Intervalo: -32.768 a 32.767

Uso: Números inteiros de tamanho médio, economizar memória

java
short anoAtual = 2024;
short populacao = 15000;

int

Tamanho: 32 bits (4 bytes)

Intervalo: -2.147.483.648 a 2.147.483.647

Uso: Tipo inteiro mais comum, padrão para números inteiros

java
int salario = 5000;
int habitantes = 1000000;
int distancia = 450;

long

Tamanho: 64 bits (8 bytes)

Intervalo: -9.223.372.036.854.775.808 a 9.223.372.036.854.775.807

Uso: Números muito grandes, timestamps, IDs únicos

java
long populacaoMundial = 8000000000L; // Note o 'L' no final
long distanciaEspacial = 384400000L; // km até a Lua
long timestamp = System.currentTimeMillis();

2.2. Tipos Numéricos de Ponto Flutuante

float

Tamanho: 32 bits (4 bytes)

Precisão: 6-7 dígitos decimais

Uso: Números decimais quando precisão extrema não é necessária

java
float altura = 1.75f; // Note o 'f' no final
float preco = 29.99f;
float temperatura = 36.5f;

double

Tamanho: 64 bits (8 bytes)

Precisão: 15-16 dígitos decimais

Uso: Padrão para números decimais, cálculos científicos

java
double pi = 3.141592653589793;
double salario = 5500.75;
double distancia = 384400.5; // Não precisa do 'd' (é o padrão)

2.3. Outros Tipos Primitivos

char

Tamanho: 16 bits (2 bytes)

Uso: Armazenar um único caractere Unicode

java
char letra = 'A';
char simbolo = '@';
char numero = '5'; // Caractere, não número!
char unicode = '\u0041'; // 'A' em Unicode

boolean

Tamanho: 1 bit (teoricamente, mas geralmente 1 byte)

Valores: true ou false

Uso: Condições lógicas, flags, estados

java
boolean estaLogado = true;
boolean temPermissao = false;
boolean maiorIdade = idade >= 18;

3. Visualização de Tamanhos em Memória

byte
1 byte
8 bits
short
2 bytes
16 bits
int
4 bytes
32 bits
long
8 bytes
64 bits
float
4 bytes
32 bits
double
8 bytes
64 bits
char
2 bytes
16 bits
boolean
1 bit
~1 byte
Tipo Tamanho Valor Padrão Exemplo
byte 1 byte 0 byte b = 100;
short 2 bytes 0 short s = 1000;
int 4 bytes 0 int i = 100000;
long 8 bytes 0L long l = 100000L;
float 4 bytes 0.0f float f = 10.5f;
double 8 bytes 0.0d double d = 10.5;
char 2 bytes '\u0000' char c = 'A';
boolean 1 bit false boolean b = true;

4. String: O Tipo Referência Mais Usado

Diferente dos tipos primitivos, String é um tipo de referência (objeto). Ela é usada para armazenar sequências de caracteres (texto).

Características da String:

  • Imutável: Uma vez criada, não pode ser modificada (operações criam novas Strings)
  • Usa aspas duplas: "texto" ao invés de aspas simples
  • Classe especial: Tem suporte especial do Java apesar de ser objeto
  • Pool de Strings: Java otimiza Strings literais na memória
java
// Declaração de Strings
String nome = "Maria Silva";
String email = "maria@email.com";
String mensagem = "Olá, mundo!";

// Concatenação
String nomeCompleto = "João" + " " + "Pedro"; // "João Pedro"
String saudacao = "Olá, " + nome + "!";

// Métodos comuns
int tamanho = nome.length(); // 11
String maiuscula = nome.toUpperCase(); // "MARIA SILVA"
String minuscula = nome.toLowerCase(); // "maria silva"
boolean contem = nome.contains("Silva"); // true
String substituido = nome.replace("Silva", "Santos"); // "Maria Santos"

// Comparação (SEMPRE use .equals para Strings!)
boolean igual = nome.equals("Maria Silva"); // true
boolean igualIgnoreCase = nome.equalsIgnoreCase("maria silva"); // true

5. Type Casting: Conversão entre Tipos

Type casting é o processo de converter um valor de um tipo para outro. Existem dois tipos principais de conversão.

5.1. Conversão Implícita (Widening)

Acontece automaticamente quando convertemos de um tipo menor para um maior. Não há perda de dados.

java
// byte → short → int → long → float → double
// Conversões automáticas (seguras)

byte b = 10;
short s = b; // byte para short (OK)
int i = s; // short para int (OK)
long l = i; // int para long (OK)
float f = l; // long para float (OK)
double d = f; // float para double (OK)

// Exemplo prático
int numeroInteiro = 100;
double numeroDecimal = numeroInteiro; // 100.0 (automático)

5.2. Conversão Explícita (Narrowing)

Requer cast manual quando convertemos de um tipo maior para um menor. Pode haver perda de dados.

java
// double → float → long → int → short → byte
// Conversões manuais (podem perder dados)

double d = 100.75;
int i = (int) d; // 100 (perde a parte decimal)

long l = 1000L;
int i2 = (int) l; // 1000 (OK, mas cuidado com números grandes)

float f = 10.5f;
int i3 = (int) f; // 10 (trunca o decimal)

// CUIDADO: Pode causar overflow
int numeroGrande = 130;
byte b = (byte) numeroGrande; // -126 (overflow!)

// Cast em expressões
double preco = 29.99;
int reais = (int) preco; // 29
int centavos = (int) ((preco - reais) * 100); // 99

5.3. Conversão com Wrapper Classes

Para converter entre primitivos e Strings, usamos classes wrapper e métodos especiais.

java
// String para primitivos
String textoNumero = "123";
int numero = Integer.parseInt(textoNumero); // 123

String textoDecimal = "45.67";
double decimal = Double.parseDouble(textoDecimal); // 45.67

String textoBoolean = "true";
boolean valor = Boolean.parseBoolean(textoBoolean); // true

// Primitivos para String
int idade = 25;
String idadeTexto = String.valueOf(idade); // "25"
// ou
String idadeTexto2 = Integer.toString(idade); // "25"
// ou (mais simples)
String idadeTexto3 = "" + idade; // "25"

// Exemplo prático: calculadora simples
String entrada = "100";
int valor1 = Integer.parseInt(entrada);
int valor2 = 50;
int resultado = valor1 + valor2; // 150
System.out.println("Resultado: " + resultado);

6. Exemplos Práticos

Exemplo 1: Calculadora de IMC

java
public class CalculadoraIMC {
    public static void main(String[] args) {
        // Diferentes tipos para diferentes propósitos
        String nome = "Carlos Silva";
        int idade = 30;
        double peso = 75.5; // kg
        double altura = 1.75; // metros
        
        // Cálculo do IMC
        double imc = peso / (altura * altura);
        
        // Exibição dos resultados
        System.out.println("=== CÁLCULO DE IMC ===");
        System.out.println("Nome: " + nome);
        System.out.println("Idade: " + idade + " anos");
        System.out.println("Peso: " + peso + " kg");
        System.out.println("Altura: " + altura + " m");
        System.out.printf("IMC: %.2f\n", imc);
        
        // Classificação
        if (imc < 18.5) {
            System.out.println("Classificação: Abaixo do peso");
        } else if (imc < 25) {
            System.out.println("Classificação: Peso normal");
        } else if (imc < 30) {
            System.out.println("Classificação: Sobrepeso");
        } else {
            System.out.println("Classificação: Obesidade");
        }
    }
}

Exemplo 2: Conversão de Temperaturas

java
import java.util.Scanner;

public class ConversorTemperatura {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        System.out.print("Digite a temperatura em Celsius: ");
        double celsius = sc.nextDouble();
        
        // Conversões com diferentes tipos
        double fahrenheit = (celsius * 9.0 / 5.0) + 32.0;
        double kelvin = celsius + 273.15;
        
        // Exibição formatada
        System.out.println("\n=== CONVERSÃO DE TEMPERATURAS ===");
        System.out.printf("%.2f°C = %.2f°F\n", celsius, fahrenheit);
        System.out.printf("%.2f°C = %.2fK\n", celsius, kelvin);
        
        // Cast para inteiro (sem decimais)
        int celsiusInt = (int) celsius;
        int fahrenheitInt = (int) fahrenheit;
        
        System.out.println("\nValores inteiros:");
        System.out.println(celsiusInt + "°C = " + fahrenheitInt + "°F");
        
        sc.close();
    }
}

Exemplo 3: Sistema de Pontos de Jogador

java
public class SistemaJogador {
    public static void main(String[] args) {
        // Tipos diferentes para dados diferentes
        String nomeJogador = "Player1";
        int nivel = 15;
        long experiencia = 1500000L; // Números grandes
        double vida = 87.5; // Porcentagem
        float mana = 42.3f; // Float para economizar memória
        boolean estaVivo = true;
        char classe = 'G'; // G = Guerreiro
        
        // Cálculos
        long expProximoNivel = 2000000L;
        long expRestante = expProximoNivel - experiencia;
        double porcentagemNivel = (experiencia * 100.0) / expProximoNivel;
        
        // Exibição do status
        System.out.println("=== STATUS DO JOGADOR ===");
        System.out.println("Nome: " + nomeJogador);
        System.out.println("Classe: " + classe);
        System.out.println("Nível: " + nivel);
        System.out.println("Experiência: " + experiencia + " XP");
        System.out.println("Falta para próximo nível: " + expRestante + " XP");
        System.out.printf("Progresso: %.1f%%\n", porcentagemNivel);
        System.out.println("Vida: " + vida + "%");
        System.out.println("Mana: " + mana + "%");
        System.out.println("Status: " + (estaVivo ? "Vivo" : "Morto"));
    }
}

Exemplo 4: Trabalhando com Bytes

java
public class ExemploBytes {
    public static void main(String[] args) {
        // Bytes são úteis para economizar memória
        byte[] idades = {25, 30, 18, 45, 60, 22};
        
        int soma = 0;
        for (byte idade : idades) {
            soma += idade; // byte é promovido para int automaticamente
        }
        
        double media = (double) soma / idades.length;
        
        System.out.println("Idades: ");
        for (byte idade : idades) {
            System.out.print(idade + " ");
        }
        System.out.println("\nSoma: " + soma);
        System.out.printf("Média: %.2f anos\n", media);
        
        // Encontrar maior e menor
        byte menor = idades[0];
        byte maior = idades[0];
        
        for (byte idade : idades) {
            if (idade < menor) menor = idade;
            if (idade > maior) maior = idade;
        }
        
        System.out.println("Menor idade: " + menor);
        System.out.println("Maior idade: " + maior);
    }
}

7. Erros Comuns e Boas Práticas

❌ Erro 1: Overflow em Tipos Pequenos

java
// ERRO: Número muito grande para byte
byte numero = 200; // ERRO! byte vai de -128 a 127

// CORRETO: Use int ou faça cast consciente
int numero = 200; // OK
byte numeroPequeno = 100; // OK (dentro do range)

❌ Erro 2: Perda de Precisão

java
// CUIDADO: Divisão inteira
int a = 5;
int b = 2;
int resultado = a / b; // 2, não 2.5!

// CORRETO: Use double para decimais
double resultado = (double) a / b; // 2.5
// ou
double resultado = 5.0 / 2.0; // 2.5

❌ Erro 3: Comparar Strings com ==

java
// ERRADO: Compara referências, não conteúdo
String nome1 = new String("Java");
String nome2 = new String("Java");
if (nome1 == nome2) { // false (referências diferentes)
    System.out.println("Iguais");
}

// CORRETO: Use .equals()
if (nome1.equals(nome2)) { // true (conteúdo igual)
    System.out.println("Iguais");
}

❌ Erro 4: Esquecer Sufixos L e F

java
// ERRO: Será tratado como int/double
long numero = 9000000000; // ERRO! Número muito grande

// CORRETO: Use sufixo L
long numero = 9000000000L; // OK

// float também precisa de sufixo
float preco = 29.99; // ERRO! Será tratado como double
float preco = 29.99f; // OK

✅ Boas Práticas:

  • Use int como padrão para números inteiros
  • Use double como padrão para números decimais
  • Use long apenas quando necessário (números muito grandes)
  • Use byte ou short para economizar memória em arrays grandes
  • Sempre adicione L em literais long e f em literais float
  • Use .equals() para comparar Strings, nunca ==
  • Tenha cuidado com casting - pode causar perda de dados
  • Evite comparações de float/double com == (use intervalos)

8. Exercícios Práticos

📝 Exercício 1: Tipos Apropriados

Declare variáveis com tipos apropriados para: nome de pessoa, idade, salário mensal, altura em metros, CPF (só números), está empregado (sim/não).

Mostrar Solução
java
public class DadosPessoa {
    public static void main(String[] args) {
        String nome = "Maria Silva";
        int idade = 28;
        double salario = 5500.75;
        double altura = 1.68;
        long cpf = 12345678900L; // long para 11 dígitos
        boolean estaEmpregado = true;
        
        System.out.println("Nome: " + nome);
        System.out.println("Idade: " + idade);
        System.out.println("Salário: R$ " + salario);
        System.out.println("Altura: " + altura + "m");
        System.out.println("CPF: " + cpf);
        System.out.println("Empregado: " + estaEmpregado);
    }
}

📝 Exercício 2: Conversões

Crie um programa que leia uma String com um número, converta para int, multiplique por 2 e exiba o resultado.

Mostrar Solução
java
import java.util.Scanner;

public class ConversaoNumero {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        System.out.print("Digite um número: ");
        String numeroTexto = sc.nextLine();
        
        // Conversão String para int
        int numero = Integer.parseInt(numeroTexto);
        
        // Cálculo
        int resultado = numero * 2;
        
        System.out.println("Número digitado: " + numero);
        System.out.println("Dobro: " + resultado);
        
        sc.close();
    }
}

📝 Exercício 3: Casting Explícito

Declare um double com valor 45.87, converta para int (perdendo os decimais) e exiba ambos os valores.

Mostrar Solução
java
public class CastingExemplo {
    public static void main(String[] args) {
        double valorOriginal = 45.87;
        int valorInteiro = (int) valorOriginal; // Cast explícito
        
        System.out.println("Valor original (double): " + valorOriginal);
        System.out.println("Valor convertido (int): " + valorInteiro);
        System.out.println("Parte perdida: " + (valorOriginal - valorInteiro));
    }
}

📝 Exercício 4: Calculadora de Média

Crie um programa que calcule a média de 3 notas (int) e exiba o resultado em double com 2 casas decimais.

Mostrar Solução
java
import java.util.Scanner;

public class CalculadoraMedia {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        System.out.print("Digite a primeira nota (0-100): ");
        int nota1 = sc.nextInt();
        
        System.out.print("Digite a segunda nota (0-100): ");
        int nota2 = sc.nextInt();
        
        System.out.print("Digite a terceira nota (0-100): ");
        int nota3 = sc.nextInt();
        
        // Cast para double para ter resultado decimal
        double media = (nota1 + nota2 + nota3) / 3.0;
        
        System.out.printf("\nMédia: %.2f\n", media);
        
        if (media >= 70) {
            System.out.println("Aprovado!");
        } else {
            System.out.println("Reprovado!");
        }
        
        sc.close();
    }
}

📝 Exercício 5: Trabalhando com Char

Peça uma letra ao usuário, converta para maiúscula e minúscula, e exiba o código Unicode dela.

Mostrar Solução
java
import java.util.Scanner;

public class ManipuladorChar {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        System.out.print("Digite uma letra: ");
        char letra = sc.next().charAt(0);
        
        // Conversões
        char maiuscula = Character.toUpperCase(letra);
        char minuscula = Character.toLowerCase(letra);
        int codigoUnicode = (int) letra; // Cast char para int
        
        System.out.println("\n=== ANÁLISE DA LETRA ===");
        System.out.println("Letra original: " + letra);
        System.out.println("Maiúscula: " + maiuscula);
        System.out.println("Minúscula: " + minuscula);
        System.out.println("Código Unicode: " + codigoUnicode);
        System.out.println("É letra? " + Character.isLetter(letra));
        System.out.println("É dígito? " + Character.isDigit(letra));
        
        sc.close();
    }
}

9. Resumo Visual

🔢 Tipos Numéricos Inteiros:

byte (1 byte): -128 a 127

short (2 bytes): -32.768 a 32.767

int (4 bytes): ~-2 bilhões a 2 bilhões

long (8 bytes): números muito grandes (sufixo L)

🔢 Tipos Numéricos Decimais:

float (4 bytes): 6-7 dígitos de precisão (sufixo f)

double (8 bytes): 15-16 dígitos de precisão (padrão)

📝 Outros Tipos:

char (2 bytes): Um único caractere (aspas simples 'A')

boolean (1 bit): true ou false

String (objeto): Sequência de caracteres (aspas duplas "texto")

🔄 Conversões:

Implícita (automática): Tipo menor → Tipo maior

Explícita (cast): Tipo maior → Tipo menor (tipo)variavel

String ↔ Primitivo: Integer.parseInt(), String.valueOf()

🌍 Uso no Mundo Real:

int: IDs, contadores, idades, quantidades

double: Preços, cálculos financeiros, medidas

String: Nomes, emails, mensagens, textos

boolean: Flags, estados, permissões

long: Timestamps, IDs grandes, estatísticas

🎯 Conclusão

Entender tipos de dados é fundamental para programar em Java de forma eficiente. Escolher o tipo correto significa usar a memória de forma inteligente e evitar erros no seu código.

Regra de ouro: Use int para inteiros, double para decimais, String para texto e boolean para sim/não. Os demais tipos use apenas quando houver necessidade específica!

Continue praticando e logo você estará escolhendo os tipos certos automaticamente!