Printf foi adicionado ao Java com a versão 1.5, mas não consigo encontrar como enviar a saída para uma string em vez de um arquivo (que é o que o sprintf faz em C). Alguém sabe como fazer isso?
Printf foi adicionado ao Java com a versão 1.5, mas não consigo encontrar como enviar a saída para uma string em vez de um arquivo (que é o que o sprintf faz em C). Alguém sabe como fazer isso?
Respostas:
// Store the formatted string in 'result'
String result = String.format("%4d", i * j);
// Write the result to standard output
System.out.println( result );
Strings são tipos imutáveis. Você não pode modificá-los, retorne apenas novas instâncias de string.
Por isso, formatar com um método de instância faz pouco sentido, pois teria que ser chamado como:
String formatted = "%s: %s".format(key, value);
Os autores Java originais (e autores .NET) decidiram que um método estático fazia mais sentido nessa situação, pois você não está modificando o destino, mas chamando um método de formato e transmitindo uma sequência de entrada.
Aqui está um exemplo de por format()
que seria burro como um método de instância. No .NET (e provavelmente em Java), Replace()
é um método de instância.
Você consegue fazer isso:
"I Like Wine".Replace("Wine","Beer");
No entanto, nada acontece, porque as strings são imutáveis. Replace()
tenta retornar uma nova string, mas não está atribuída a nada.
Isso causa muitos erros comuns de novatos, como:
inputText.Replace(" ", "%20");
Novamente, nada acontece; em vez disso, você deve fazer:
inputText = inputText.Replace(" ","%20");
Agora, se você entende que as cordas são imutáveis, isso faz todo o sentido. Se não, então você está apenas confuso. O local apropriado para Replace()
seria onde format()
está, como um método estático de String
:
inputText = String.Replace(inputText, " ", "%20");
Agora não há dúvida sobre o que está acontecendo.
A verdadeira questão é: por que os autores dessas estruturas decidiram que um deveria ser um método de instância e o outro estático? Na minha opinião, ambos são expressos de forma mais elegante como métodos estáticos.
Independentemente da sua opinião, a verdade é que você é menos propenso a cometer um erro ao usar a versão estática, e o código é mais fácil de entender (sem dicas ocultas).
Claro que existem alguns métodos que são perfeitos como métodos de instância, pegue String.Length ()
int length = "123".Length();
Nessa situação, é óbvio que não estamos tentando modificar "123", apenas estamos inspecionando e retornando seu comprimento. Este é um candidato perfeito para um método de instância.
Minhas regras simples para métodos de instância em objetos imutáveis:
Ambas as soluções funcionam para simular a impressão, mas de uma maneira diferente. Por exemplo, para converter um valor em uma sequência hexadecimal, você tem as 2 soluções a seguir:
com format()
, o mais próximo de sprintf()
:
final static String HexChars = "0123456789abcdef";
public static String getHexQuad(long v) {
String ret;
if(v > 0xffff) ret = getHexQuad(v >> 16); else ret = "";
ret += String.format("%c%c%c%c",
HexChars.charAt((int) ((v >> 12) & 0x0f)),
HexChars.charAt((int) ((v >> 8) & 0x0f)),
HexChars.charAt((int) ((v >> 4) & 0x0f)),
HexChars.charAt((int) ( v & 0x0f)));
return ret;
}
com replace(char oldchar , char newchar)
, um pouco mais rápido, mas bastante limitado:
...
ret += "ABCD".
replace('A', HexChars.charAt((int) ((v >> 12) & 0x0f))).
replace('B', HexChars.charAt((int) ((v >> 8) & 0x0f))).
replace('C', HexChars.charAt((int) ((v >> 4) & 0x0f))).
replace('D', HexChars.charAt((int) ( v & 0x0f)));
...
Existe uma terceira solução que consiste em adicionar o caractere ret
um a um (char são números que se somam !), Como em:
...
ret += HexChars.charAt((int) ((v >> 12) & 0x0f)));
ret += HexChars.charAt((int) ((v >> 8) & 0x0f)));
...
... mas isso seria muito feio.
Você pode fazer um printf para qualquer coisa que seja um OutputStream com um PrintStream. De alguma forma, imprimindo em um fluxo de string:
PrintStream ps = new PrintStream(baos);
ps.printf("there is a %s from %d %s", "hello", 3, "friends");
System.out.println(baos.toString());
baos.reset(); //need reset to write new string
ps.printf("there is a %s from %d %s", "flip", 5, "haters");
System.out.println(baos.toString());
baos.reset();
O fluxo da sequência pode ser criado assim: ByteArrayOutputStream:
ByteArrayOutputStream baos = new ByteArrayOutputStream();