Conversões de String em Java
Converta entre strings e primitivos em Java — Integer.parseInt, Double.parseDouble, String.valueOf e muito mais.
A maioria dos dados chega como texto e a maioria dos dados sai como texto. Entre esses dois limites, eles geralmente vivem na forma de algo mais útil — um int, um double, um boolean, um LocalDate. Este capítulo trata das duas direções de conversão entre String e os tipos primitivos, os tipos wrapper e os arrays de caracteres.
Há um pequeno vocabulário que vale a pena memorizar; uma vez que você o conheça, a resposta para "como transformo esta string em um X" é uma linha de código em qualquer situação.
String → primitivo: a família parse...
Cada classe wrapper possui um método estático que recebe uma String e retorna o primitivo correspondente:
int i = Integer.parseInt("42");
long l = Long.parseLong("9999999999");
double d = Double.parseDouble("3.14");
float f = Float.parseFloat("3.14");
short s = Short.parseShort("32000");
byte b = Byte.parseByte("127");
boolean ok = Boolean.parseBoolean("true"); // any case-insensitive "true"; everything else → falseEssas são as ferramentas padrão. Elas lançam NumberFormatException para entradas que não fazem parse — incluindo null, strings vazias, strings com espaços, decimais específicos de localidade como "3,14" e valores fora do intervalo.
Integer.parseInt(" 42 "); // NumberFormatException — trim first
Integer.parseInt("3.0"); // NumberFormatException — that's a double
Integer.parseInt("1234567890123"); // NumberFormatException — overflows intInteger.parseInt aceita um segundo argumento opcional para a base numérica:
Integer.parseInt("ff", 16); // 255
Integer.parseInt("1010", 2); // 10
Integer.parseInt("777", 8); // 511 — the radix is the second arg, not a prefix
Integer.parseInt("0x1A", 16); // NumberFormatException — no "0x" prefix; pass just "1A"parseInt lê os dígitos literais na base que você passa; ele não entende prefixos de código-fonte como 0x ou um 0 inicial para octal. Portanto, Integer.parseInt("0777", 8) funciona bem — o 0 inicial é simplesmente mais um dígito octal — mas Integer.parseInt("0x1A", 16) lança uma exceção, porque x não é um dígito de base 16. Remova qualquer prefixo você mesmo antes de fazer o parse.
Para interpretação sem sinal do bit mais significativo em valores de 32 e 64 bits, o JDK oferece Integer.parseUnsignedInt e Long.parseUnsignedLong.
String → wrapper: valueOf vs parse...
O valueOf estático em cada wrapper faz o mesmo parse, mas retorna o tipo wrapper:
Integer n = Integer.valueOf("42"); // Integer, not int
Double d = Double.valueOf("3.14"); // Double, not doubleOs dois diferem em três pontos que ocasionalmente importam:
- Tipo de retorno.
parseInt→int,valueOf→Integer. Escolha o que seu destino exige. - Cache.
Integer.valueOf(int)eLong.valueOf(long)armazenam em cache números pequenos (-128..127por padrão), retornando a mesma instância deIntegerem chamadas repetidas.parseIntretorna um primitivo, então o cache não tem relevância — mas quando você estaria encaixotando o resultado de qualquer forma,valueOfé mais eficiente. - Comportamento em overflow. Idêntico — ambos lançam
NumberFormatException.
Regra prática: se você quer um primitivo, use parseInt; se você quer um wrapper, use valueOf. Não escreva Integer.valueOf(Integer.parseInt(s)) — isso é código de dois parses para um resultado de um parse.
Primitivo → String: String.valueOf e similares
A direção inversa tem duas ferramentas bem nomeadas:
String s1 = String.valueOf(42); // "42"
String s2 = String.valueOf(3.14); // "3.14"
String s3 = String.valueOf(true); // "true"
String s4 = String.valueOf('a'); // "a"
String s5 = String.valueOf(new char[]{'h','i'}); // "hi"
String s6 = String.valueOf((Object) null); // "null" — NOT an NPETodo wrapper também possui um toString que recebe o primitivo:
Integer.toString(42); // "42"
Integer.toString(255, 16); // "ff" — radix overload
Long.toString(123456789L); // "123456789"
Double.toString(3.14); // "3.14"E, claro, a concatenação com "" funciona:
String s = "" + 42; // "42"String.valueOf é o mais geral e o estilo mais defensável — nunca lança exceção com null e lida com todos os primitivos mais Object. Para formatação numérica onde você precisa de largura, sinal, agrupamento ou decimais com reconhecimento de localidade, use String.format.
Strings e chars
Um char é um primitivo (uma unidade de código UTF-16); uma String é uma sequência deles. Conversões nas duas direções:
String s = String.valueOf('a'); // "a"
char c1 = "abc".charAt(0); // 'a'
char[] arr = "abc".toCharArray(); // ['a', 'b', 'c']
String s2 = new String(arr); // "abc"
String s3 = new String(arr, 1, 2); // "bc" — offset + countString.toCharArray() sempre retorna um array novo e modificável. Essa é a ferramenta certa quando você precisa modificar caracteres (por exemplo, para limpar um buffer de senha) — a própria String não pode oferecer uma visão mutável.
Strings e bytes
Bytes são o formato de transmissão; strings são a forma em memória. A conversão sempre envolve um charset, e a resposta certa é sempre passá-lo explicitamente:
byte[] bytes = "héllo".getBytes(StandardCharsets.UTF_8);
String back = new String(bytes, StandardCharsets.UTF_8);As sobrecargas sem argumentos (getBytes(), new String(bytes)) usam o charset padrão da JVM, que depende da plataforma e é uma fonte constante de bugs do tipo "funciona na minha máquina". Sempre passe um Charset. UTF-8 é o padrão correto para código novo; sistemas legados às vezes precisam de Latin-1 ou uma das páginas de código do Windows.
Conversões que não existem
Algumas conversões que as pessoas buscam e que não estão disponíveis:
int→charpelo valor do dígito.(char) 5é o caractere de controle no ponto de código 5, não'5'. UseCharacter.forDigit(5, 10)ou(char) ('0' + 5).char→intpelo valor do dígito.(int) '5'é 53, não 5. UseCharacter.digit('5', 10)ou'5' - '0'.String→ numérico com valor padrão em caso de falha. Java não possui umparseIntOrDefault. A versão idiomática é um pequeno helper:
static int parseIntOr(String s, int fallback) {
try { return Integer.parseInt(s); }
catch (NumberFormatException e) { return fallback; }
}Conversão não é validação
O maior erro com conversão de string para primitivo é tratar um parse bem-sucedido como uma validação bem-sucedida. Integer.parseInt("0") retorna 0 para qualquer entrada que o usuário digitar como zero, incluindo "0", "00", "+0" e "-0" — todos fazem parse para o mesmo valor. Se você se importa se a entrada era canônica, faça o parse e depois converta de volta:
int v = Integer.parseInt(input);
if (!Integer.toString(v).equals(input)) {
throw new IllegalArgumentException("non-canonical integer: " + input);
}Para entradas numéricas de formulários voltados ao usuário, valide o formato primeiro (regex, comprimento, caracteres permitidos), depois faça o parse. Não confie no parser para dizer se a entrada era razoável.
Um exemplo prático
Um programa que converte nas duas direções nos tipos mais comuns, incluindo um helper robusto com valor padrão em caso de falha, uma ida e volta em hex e uma ida e volta de bytes/string com UTF-8.
Três detalhes para observar na saída. A string héllo faz a ida e volta pelo UTF-8 sem problemas — cinco caracteres se tornam seis bytes (o é ocupa dois), e os bytes resultantes fazem parse de volta nos mesmos cinco caracteres. O String.valueOf((Object)null) produz "null" em vez de lançar uma exceção — isso é intencional; é por isso que "x = " + nullable não quebra. E o helper parseIntOr lida com entrada inválida, entrada com espaços e entrada null sem que o site de chamada precise saber.
O que vem a seguir
O capítulo que encerra a Parte 9 aborda os dois métodos mais usados de "string entra, lista sai / lista entra, string sai" na biblioteca padrão — e as variantes com regex que ficam por baixo deles. Continue em Java String split() e join().