Tipos de Dados em Java
Explore os tipos de dados primitivos do Java (byte, short, int, long, float, double, char, boolean) e os tipos de referência.
Java é estaticamente tipado — toda variável tem um tipo conhecido em tempo de compilação. Os tipos se dividem em duas famílias: primitivos (valores brutos incorporados à linguagem) e tipos de referência (objetos, arrays e tudo o que é criado com new). Este capítulo percorre os dois.
Os oito tipos primitivos
Os primitivos são os únicos valores em Java que não são objetos. Eles armazenam seu valor diretamente no espaço de armazenamento da variável. Java define exatamente oito:
| Tipo | Tamanho | Intervalo | Padrão | Exemplo de literal |
|---|---|---|---|---|
byte | 8 bits | -128 a 127 | 0 | byte b = 100; |
short | 16 bits | -32.768 a 32.767 | 0 | short s = 30000; |
int | 32 bits | -2³¹ a 2³¹-1 (≈ ±2,1 bilhões) | 0 | int i = 1_000_000; |
long | 64 bits | -2⁶³ a 2⁶³-1 | 0L | long l = 9_000L; |
float | 32 bits | precisão simples IEEE 754 | 0.0f | float f = 3.14f; |
double | 64 bits | precisão dupla IEEE 754 | 0.0 | double d = 3.14; |
char | 16 bits | Unidade de código Unicode (U+0000 a U+FFFF) | \0 | char c = 'A'; |
boolean | definido pela JVM | true ou false | false | boolean b = true; |
Algumas coisas que valem a pena memorizar:
inté o tipo inteiro padrão. A maioria dos contadores e índices sãoint. Uselongsomente quando precisar de números acima de ~2 bilhões.doubleé o tipo de ponto flutuante padrão. O simples3.14é umdouble;3.14fé umfloat. Usedoublea menos que a pressão de memória force o uso defloat.- Underscores em literais numéricos melhoram a legibilidade:
1_000_000é o mesmo que1000000. - Valores padrão se aplicam apenas a campos, não a variáveis locais. Uma variável local não tem padrão — você deve inicializá-la antes de lê-la.
Tipos de referência
Todo o resto — String, arrays, suas próprias classes, classes de biblioteca — é um tipo de referência. Uma variável de tipo de referência não contém o objeto em si; ela contém uma referência (essencialmente um ponteiro) para o objeto na heap:
String name = "Ada";
int[] scores = new int[10];
LocalDate today = LocalDate.now();O valor padrão de qualquer variável de referência é null — um valor especial que significa "nenhum objeto."
String s = null;
System.out.println(s.length()); // throws NullPointerException at runtimenull é a origem de um dos erros de tempo de execução mais comuns em Java. O capítulo Java Exceptions cobre como lidar com a NullPointerException que isso provoca.
Classes wrapper
Cada primitivo tem uma classe wrapper correspondente — um objeto real que envolve o valor primitivo:
| Primitivo | Wrapper |
|---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
Você precisa de wrappers quando quer colocar primitivos em coleções (que só armazenam objetos):
List<Integer> scores = new ArrayList<>();
scores.add(42); // autoboxed from int → Integer
int first = scores.get(0); // unboxed from Integer → intJava converte automaticamente entre primitivos e wrappers — chamado de autoboxing e unboxing — então na maioria das vezes você não percebe.
Uma nota sobre String
String é um tipo de referência, não um primitivo. É especial o suficiente para que a linguagem lhe conceda uma sintaxe literal ("texto") e o operador +. Strings são imutáveis — uma vez criadas, seu conteúdo nunca muda. Cada "modificação" retorna uma nova string. O capítulo Java Strings aprofunda o tema.
Escolhendo um tipo
Uma pequena árvore de decisão para o Java do dia a dia:
- Contar coisas ou índices de arrays →
int - Contagens grandes (tamanhos de arquivo, timestamps em milissegundos) →
long - Dinheiro →
BigDecimal(nãodouble— o arredondamento de ponto flutuante vai te pegar) - Caractere único →
char - Sim/Não →
boolean - Texto →
String - Uma data ou hora → tipos em
java.time(LocalDate,Instant,Duration)
Resista ao impulso de "economizar memória" usando byte ou short para inteiros comuns. As JVMs são otimizadas para operações com int; short na verdade não usa menos memória na maioria dos casos.
Armadilhas comuns
Alguns comportamentos de tipo surpreendem iniciantes com frequência. Conhecê-los de antemão poupa horas de depuração.
Overflow de inteiros envolve silenciosamente
A aritmética inteira em Java nunca lança exceção em caso de overflow — ela faz wrap-around. Adicionar 1 ao maior int produz o menor int:
int max = Integer.MAX_VALUE; // 2147483647
System.out.println(max + 1); // -2147483648Se um valor puder exceder ~2,1 bilhões, use long. Para contagens que possam ultrapassar até mesmo long, recorra a BigInteger.
Ponto flutuante não é exato
float e double seguem o padrão IEEE 754, que não pode representar a maioria das frações decimais com exatidão. O exemplo clássico:
System.out.println(0.1 + 0.2); // 0.30000000000000004É por isso que você nunca deve usar double para dinheiro. Use BigDecimal (construído a partir de uma String, por exemplo, new BigDecimal("0.1")) quando valores decimais exatos importarem.
char é um número
Um char é um inteiro de 16 bits sem sinal que contém uma unidade de código Unicode, portanto participa de operações aritméticas:
char a = 'A';
System.out.println((int) a); // 65
System.out.println((char) (a + 1)); // BCompare wrappers com .equals(), não com ==
== em objetos wrapper compara referências, não valores. Por causa de um cache de autoboxing para valores pequenos de Integer (-128 a 127), == parece funcionar para números pequenos e depois falha para números grandes:
Integer a = 127, b = 127;
System.out.println(a == b); // true (cached)
Integer c = 128, d = 128;
System.out.println(c == d); // false (different objects)
System.out.println(c.equals(d)); // true (compares values)Sempre use .equals() para comparar valores de wrapper. Veja Java Type Casting para as regras de conversão entre esses tipos.
Uma demonstração funcionando
O que vem a seguir
Java Type Casting mostra como converter entre tipos numéricos e entre tipos de referência relacionados.