Printf se agregó a Java con la versión 1.5, pero parece que no puedo encontrar cómo enviar la salida a una cadena en lugar de a un archivo (que es lo que hace sprintf en C). ¿Alguien sabe como hacer esto?
Printf se agregó a Java con la versión 1.5, pero parece que no puedo encontrar cómo enviar la salida a una cadena en lugar de a un archivo (que es lo que hace sprintf en C). ¿Alguien sabe como hacer esto?
Respuestas:
// Store the formatted string in 'result'
String result = String.format("%4d", i * j);
// Write the result to standard output
System.out.println( result );
Las cadenas son tipos inmutables. No puede modificarlos, solo devuelve nuevas instancias de cadena.
Debido a eso, el formateo con un método de instancia tiene poco sentido, ya que debería llamarse así:
String formatted = "%s: %s".format(key, value);
Los autores originales de Java (y los autores de .NET) decidieron que un método estático tenía más sentido en esta situación, ya que no está modificando el objetivo, sino que llama a un método de formato y pasa una cadena de entrada.
Aquí hay un ejemplo de por qué format()
sería tonto como método de instancia. En .NET (y probablemente en Java), Replace()
es un método de instancia.
Puedes hacerlo:
"I Like Wine".Replace("Wine","Beer");
Sin embargo, no pasa nada, porque las cadenas son inmutables. Replace()
intenta devolver una nueva cadena, pero no está asignada a nada.
Esto causa muchos errores comunes de novatos como:
inputText.Replace(" ", "%20");
Nuevamente, no pasa nada, en su lugar debes hacer:
inputText = inputText.Replace(" ","%20");
Ahora, si comprende que las cadenas son inmutables, eso tiene mucho sentido. Si no lo haces, entonces estás confundido. El lugar adecuado para Replace()
sería donde format()
está, como método estático de String
:
inputText = String.Replace(inputText, " ", "%20");
Ahora no hay dudas sobre lo que está pasando.
La verdadera pregunta es, ¿por qué los autores de estos marcos decidieron que uno debería ser un método de instancia y el otro estático? En mi opinión, ambos se expresan con más elegancia como métodos estáticos.
Independientemente de su opinión, la verdad es que es menos propenso a cometer un error al usar la versión estática, y el código es más fácil de entender (sin problemas ocultos).
Por supuesto, hay algunos métodos que son perfectos como métodos de instancia, tome String.Length ()
int length = "123".Length();
En esta situación, es obvio que no estamos tratando de modificar "123", solo lo estamos inspeccionando y devolviendo su longitud. Este es un candidato perfecto para un método de instancia.
Mis reglas simples para los métodos de instancia en objetos inmutables:
Ambas soluciones funcionan para simular printf, pero de una manera diferente. Por ejemplo, para convertir un valor en una cadena hexadecimal, tiene las 2 soluciones siguientes:
con format()
, más cercano a 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;
}
con replace(char oldchar , char newchar)
, algo más rápido pero 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)));
...
Hay una tercera solución que consiste en agregar el carácter ret
uno por uno (¡los números de caracteres se suman entre sí !) Como en:
...
ret += HexChars.charAt((int) ((v >> 12) & 0x0f)));
ret += HexChars.charAt((int) ((v >> 8) & 0x0f)));
...
... pero eso sería realmente feo.
Puede hacer una impresión a cualquier cosa que sea un OutputStream con un PrintStream. De alguna manera como esta, imprimiendo en una secuencia de cadena:
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();
La secuencia de cadena se puede crear así: ByteArrayOutputStream:
ByteArrayOutputStream baos = new ByteArrayOutputStream();