Printf è stato aggiunto a Java con la versione 1.5 ma non riesco a trovare come inviare l'output a una stringa anziché a un file (che è ciò che fa Sprintf in C). Qualcuno sa come fare questo?
Printf è stato aggiunto a Java con la versione 1.5 ma non riesco a trovare come inviare l'output a una stringa anziché a un file (che è ciò che fa Sprintf in C). Qualcuno sa come fare questo?
Risposte:
// Store the formatted string in 'result'
String result = String.format("%4d", i * j);
// Write the result to standard output
System.out.println( result );
Le stringhe sono tipi immutabili. Non è possibile modificarli, restituire solo nuove istanze di stringa.
Per questo motivo, la formattazione con un metodo di istanza ha poco senso, poiché dovrebbe essere chiamata come:
String formatted = "%s: %s".format(key, value);
Gli autori Java originali (e gli autori .NET) hanno deciso che un metodo statico aveva più senso in questa situazione, poiché non si modifica la destinazione, ma si chiama un metodo di formattazione e si passa una stringa di input.
Ecco un esempio del perché format()
sarebbe stupido come metodo di istanza. In .NET (e probabilmente in Java), Replace()
è un metodo di istanza.
Puoi farlo:
"I Like Wine".Replace("Wine","Beer");
Tuttavia, non succede nulla, perché le stringhe sono immutabili. Replace()
tenta di restituire una nuova stringa, ma non è assegnata a nulla.
Ciò provoca molti errori rookie comuni come:
inputText.Replace(" ", "%20");
Ancora una volta, non succede nulla, invece devi fare:
inputText = inputText.Replace(" ","%20");
Ora, se capisci che le stringhe sono immutabili, ha perfettamente senso. Se non lo fai, allora sei solo confuso. Il posto giusto per Replace()
sarebbe dove si format()
trova, come metodo statico di String
:
inputText = String.Replace(inputText, " ", "%20");
Ora non ci sono dubbi su cosa stia succedendo.
La vera domanda è: perché gli autori di questi framework hanno deciso che uno dovrebbe essere un metodo di istanza e l'altro statico? A mio avviso, entrambi sono più elegantemente espressi come metodi statici.
Indipendentemente dalla tua opinione, la verità è che sei meno incline a fare un errore usando la versione statica, e il codice è più facile da capire (No Hidden Gotchas).
Naturalmente ci sono alcuni metodi che sono perfetti come metodi di istanza, prendi String.Length ()
int length = "123".Length();
In questa situazione, è ovvio che non stiamo cercando di modificare "123", stiamo solo controllando e restituendo la sua lunghezza. Questo è un candidato perfetto per un metodo di istanza.
Le mie semplici regole per i metodi di istanza su oggetti immutabili:
Entrambe le soluzioni funzionano per simulare printf, ma in modo diverso. Ad esempio, per convertire un valore in una stringa esadecimale, sono disponibili le 2 soluzioni seguenti:
con format()
, il più vicino 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)
, un po 'più veloce ma piuttosto limitato:
...
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)));
...
Esiste una terza soluzione che consiste nell'aggiungere il carattere ret
uno per uno (i caratteri sono numeri che si aggiungono l'un l'altro !) Come in:
...
ret += HexChars.charAt((int) ((v >> 12) & 0x0f)));
ret += HexChars.charAt((int) ((v >> 8) & 0x0f)));
...
... ma sarebbe davvero brutto.
È possibile eseguire una stampa su qualsiasi cosa sia OutputStream con PrintStream. In qualche modo, stampando in un flusso di stringhe:
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();
Il flusso di stringhe può essere creato in questo modo ByteArrayOutputStream:
ByteArrayOutputStream baos = new ByteArrayOutputStream();