Números em Java
Trabalhe com tipos numéricos em Java — int, long, float, double — e entenda precisão, overflow e a classe Number.
Java distingue números inteiros e de ponto flutuante, e dentro de cada família há vários tamanhos. Escolher o tipo correto é importante tanto para a correção (precisão, intervalo) quanto para o desempenho. Este capítulo é um guia focado nos tipos numéricos, seus literais, conversões e as armadilhas que pegam iniciantes de surpresa. Ele assume que você já sabe como declarar uma variável e já viu o conjunto completo de tipos de dados primitivos.
Os primitivos numéricos
| Tipo | Bits | Intervalo | Estilo de literal padrão |
|---|---|---|---|
byte | 8 | -128 a 127 | byte b = 10; |
short | 16 | -32.768 a 32.767 | short s = 30_000; |
int | 32 | -2³¹ a 2³¹-1 (≈ ±2,1 bilhões) | int i = 1_000_000; |
long | 64 | -2⁶³ a 2⁶³-1 | long l = 9_000L; |
float | 32 | IEEE 754 precisão simples (~7 dígitos) | float f = 3.14f; |
double | 64 | IEEE 754 precisão dupla (~16 dígitos) | double d = 3.14; |
No dia a dia com Java:
- Use
intpara contadores, índices e a maioria dos valores inteiros. - Use
longquando você pode ultrapassar ~2 bilhões (tamanhos de arquivo, milissegundos desde a época, geradores de ID). - Use
doublepara cálculos de ponto flutuante. - Use
floatapenas quando a memória é limitada ou uma API exige.
Literais inteiros
Dígitos simples são int:
int answer = 42;
int million = 1_000_000; // underscores are ignoredSufixo L (maiúsculo preferido) para long:
long big = 9_000_000_000L;Prefixo 0x para hex, 0b para binário, 0 para octal:
int hex = 0xFF; // 255
int bin = 0b1010; // 10
int oct = 0755; // 493 — be careful, easy to write by accident(Literais octais são uma fonte frequente de bugs — 0123 não é 123, é 83. Evite zeros à esquerda a menos que realmente queira octal.)
Literais de ponto flutuante
Decimais simples são double:
double pi = 3.14159;
double e = 2.71828;Sufixo f para float, d para double explícito (opcional):
float pif = 3.14f;
double pid = 3.14d;Notação científica funciona:
double avogadro = 6.022e23;
double tiny = 1.0e-9;Convertendo entre tipos numéricos
Java realiza uma conversão de alargamento automaticamente quando um tipo menor flui para um maior (nenhum dado pode ser perdido):
int x = 7;
double promoted = x; // 7.0 — int widens to double automaticallyO caminho inverso é o estreitamento: o valor pode não caber, então Java força você a escrever um cast explícito e descarta silenciosamente o que não couber. Truncamento, não arredondamento:
double d = 9.99;
int i = (int) d; // 9 — the fraction is dropped, never rounded
long big = 9_000_000_000L;
int truncated = (int) big; // 410065408 — high bits lost, value is garbagePor causa disso, só estreite quando tiver certeza de que o valor cabe. Para arredondar um double para o inteiro mais próximo em vez de truncar, use Math.round (veja Java Math).
Conversões também acontecem dentro de expressões. A divisão inteira descarta o resto, o que surpreende iniciantes:
System.out.println(7 / 2); // 3 — both operands are int, so int division
System.out.println(7 / 2.0); // 3.5 — one double operand promotes the whole expressionPara as regras completas sobre casts explícitos, veja Java Type Casting.
Overflow
A aritmética inteira envolve silenciosamente os limites do tipo. Nenhuma exceção é lançada:
int max = Integer.MAX_VALUE;
System.out.println(max + 1); // -2147483648 (Integer.MIN_VALUE)Para aritmética com verificação de overflow, use a família Math.exact:
Math.addExact(Integer.MAX_VALUE, 1); // throws ArithmeticException
Math.multiplyExact(100_000, 100_000); // throws tooÚtil quando a correção importa mais que o desempenho — cálculos financeiros, tamanhos de alocação, etc.
Precisão de ponto flutuante
double e float são IEEE 754 binário — eles não conseguem representar a maioria das frações decimais com exatidão:
System.out.println(0.1 + 0.2); // 0.30000000000000004Nunca compare valores de ponto flutuante com ==. Compare dentro de uma tolerância:
double diff = Math.abs(a - b);
if (diff < 1e-9) { /* close enough */ }Para quantias monetárias ou em qualquer lugar onde você precisa de aritmética decimal exata, use BigDecimal:
import java.math.BigDecimal;
BigDecimal sum = new BigDecimal("0.1").add(new BigDecimal("0.2"));
System.out.println(sum); // 0.3Sempre passe strings para new BigDecimal(...). O construtor com double reintroduziria a inexatidão binária.
Valores especiais de ponto flutuante
double tem três valores que não são números comuns:
double posInf = Double.POSITIVE_INFINITY;
double negInf = Double.NEGATIVE_INFINITY;
double nan = Double.NaN;
System.out.println(1.0 / 0); // Infinity
System.out.println(-1.0 / 0); // -Infinity
System.out.println(0.0 / 0); // NaN
System.out.println(nan == nan); // false — NaN compares unequal to everything
System.out.println(Double.isNaN(nan)); // trueUse Double.isNaN(x) para testar NaN; == não funcionará.
As classes wrapper
Cada primitivo tem um wrapper correspondente: Byte, Short, Integer, Long, Float, Double. Os wrappers estendem a classe abstrata Number. Você precisa deles quando:
- Usar coleções que armazenam objetos:
List<Integer>,Map<String, Double>. - Converter de strings:
Integer.parseInt("42"),Double.parseDouble("3.14"). - Converter para um tipo numérico diferente via
.intValue(),.doubleValue(), etc.
Java faz autoboxing entre primitivo e wrapper automaticamente:
List<Integer> ids = new ArrayList<>();
ids.add(42); // autobox: int → Integer
int first = ids.get(0); // unbox: Integer → intBigInteger e BigDecimal
Quando os números podem ser maiores que long ou você precisa de precisão decimal:
import java.math.BigInteger;
BigInteger huge = new BigInteger("123456789012345678901234567890");
huge.multiply(huge);
BigDecimal price = new BigDecimal("19.95");
BigDecimal tax = price.multiply(new BigDecimal("0.07"));São mais lentos que os primitivos, mas para os casos que precisam deles, é a troca certa.
Uma demonstração
O que vem a seguir
- Java Math —
Math.abs,Math.round,Math.powe o restante do kit de ferramentas numérico. - Java Operators — como os operadores aritméticos, de comparação e bit a bit se comportam nesses tipos.
- Java Booleans — o tipo de dois valores do Java, com muito menos detalhes.