Printf a été ajouté à Java avec la version 1.5, mais je n'arrive pas à trouver comment envoyer la sortie à une chaîne plutôt qu'à un fichier (ce que fait sprintf en C). Est-ce que quelqu'un sait comment faire ça?
Printf a été ajouté à Java avec la version 1.5, mais je n'arrive pas à trouver comment envoyer la sortie à une chaîne plutôt qu'à un fichier (ce que fait sprintf en C). Est-ce que quelqu'un sait comment faire ça?
Réponses:
// Store the formatted string in 'result'
String result = String.format("%4d", i * j);
// Write the result to standard output
System.out.println( result );
Les chaînes sont des types immuables. Vous ne pouvez pas les modifier, renvoyez uniquement de nouvelles instances de chaîne.
Pour cette raison, le formatage avec une méthode d'instance n'a pas de sens, car il faudrait l'appeler comme:
String formatted = "%s: %s".format(key, value);
Les auteurs Java d'origine (et les auteurs .NET) ont décidé qu'une méthode statique avait plus de sens dans cette situation, car vous ne modifiez pas la cible, mais appelez plutôt une méthode de formatage et passez une chaîne d'entrée.
Voici un exemple de pourquoi format()
serait stupide comme méthode d'instance. En .NET (et probablement en Java), Replace()
est une méthode d'instance.
Tu peux le faire:
"I Like Wine".Replace("Wine","Beer");
Cependant, rien ne se passe, car les chaînes sont immuables. Replace()
essaie de renvoyer une nouvelle chaîne, mais elle n'est affectée à rien.
Cela provoque de nombreuses erreurs de recrue courantes comme:
inputText.Replace(" ", "%20");
Encore une fois, rien ne se passe, vous devez plutôt faire:
inputText = inputText.Replace(" ","%20");
Maintenant, si vous comprenez que les chaînes sont immuables, cela est parfaitement logique. Si vous ne le faites pas, alors vous êtes simplement confus. L'endroit approprié Replace()
serait où format()
est, en tant que méthode statique de String
:
inputText = String.Replace(inputText, " ", "%20");
Maintenant, il ne fait aucun doute de ce qui se passe.
La vraie question est, pourquoi les auteurs de ces frameworks ont-ils décidé que l'une devait être une méthode d'instance et l'autre statique? À mon avis, les deux sont plus élégamment exprimés en tant que méthodes statiques.
Quelle que soit votre opinion, la vérité est que vous êtes moins enclin à faire une erreur en utilisant la version statique, et le code est plus facile à comprendre (No Hidden Gotchas).
Bien sûr, certaines méthodes sont parfaites comme méthodes d'instance, prenez String.Length ()
int length = "123".Length();
Dans cette situation, il est évident que nous n'essayons pas de modifier "123", nous l'inspectons simplement et retournons sa longueur. C'est un candidat parfait pour une méthode d'instance.
Mes règles simples pour les méthodes d'instance sur les objets immuables:
Les deux solutions fonctionnent pour simuler printf, mais d'une manière différente. Par exemple, pour convertir une valeur en chaîne hexadécimale, vous avez les 2 solutions suivantes:
avec format()
, le plus proche 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;
}
avec replace(char oldchar , char newchar)
, un peu plus rapide mais assez limité:
...
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)));
...
Il existe une troisième solution consistant à simplement ajouter le caractère ret
un par un (les caractères sont des nombres qui s'ajoutent les uns aux autres !) Comme dans:
...
ret += HexChars.charAt((int) ((v >> 12) & 0x0f)));
ret += HexChars.charAt((int) ((v >> 8) & 0x0f)));
...
... mais ce serait vraiment moche.
Vous pouvez faire un printf sur tout ce qui est un OutputStream avec un PrintStream. En quelque sorte comme ça, en imprimant dans un flux de chaînes:
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();
Le flux de chaînes peut être créé comme ceci ByteArrayOutputStream:
ByteArrayOutputStream baos = new ByteArrayOutputStream();