回答:
文字列は不変の型です。それらを変更することはできません。新しい文字列インスタンスのみを返します。
そのため、次のように呼び出す必要があるため、インスタンスメソッドを使用したフォーマットはほとんど意味がありません。
String formatted = "%s: %s".format(key, value);
元のJavaの作成者(および.NETの作成者)は、ターゲットを変更するのではなく、フォーマットメソッドを呼び出して入力文字列を渡すため、この状況では静的メソッドがより適切であると判断しました。
これがformat()
インスタンスメソッドとして馬鹿げている理由の例です。.NET(およびおそらくJava)ではReplace()
、インスタンスメソッドです。
あなたはこれを行うことができます:
"I Like Wine".Replace("Wine","Beer");
ただし、文字列は不変であるため、何も起こりません。Replace()
新しい文字列を返そうとしますが、何も割り当てられていません。
これは、次のような多くの一般的な新人のミスを引き起こします:
inputText.Replace(" ", "%20");
繰り返しになりますが、何も起こらず、代わりに次のことを行う必要があります。
inputText = inputText.Replace(" ","%20");
ここで、文字列が不変であることを理解すれば、それは完全に理にかなっています。そうしないと、混乱してしまいます。の適切な場所は、静的メソッドとしてのReplace()
場所format()
ですString
:
inputText = String.Replace(inputText, " ", "%20");
今、何が起こっているのかについて疑問はありません。
本当の問題は、なぜこれらのフレームワークの作成者は、1つをインスタンスメソッドに、もう1つを静的メソッドにすべきだと決めたのですか?私の意見では、どちらも静的メソッドとしてよりエレガントに表現されています。
あなたの意見に関係なく、真実はあなたが静的バージョンを使用して間違いを犯す傾向が少なく、コードが理解しやすいことです(隠された問題はありません)。
もちろん、インスタンスメソッドとして完璧ないくつかのメソッドがあります。String.Length()を使用してください。
int length = "123".Length();
この状況では、「123」を変更しようとしているのではなく、検査して長さを返すだけであることは明らかです。これは、インスタンスメソッドの完全な候補です。
不変オブジェクトのインスタンスメソッドの簡単なルール:
どちらのソリューションもprintfをシミュレートしますが、方法は異なります。たとえば、値を16進文字列に変換するには、次の2つの解決策があります。
とformat()
、に最も近い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;
}
でreplace(char oldchar , char newchar)
、やや高速ですがかなり制限されています:
...
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)));
...
次のように、charをret
1つずつ追加することで構成される3番目の解決策があります(charは互いに加算される数値です)。
...
ret += HexChars.charAt((int) ((v >> 12) & 0x0f)));
ret += HexChars.charAt((int) ((v >> 8) & 0x0f)));
...
...しかし、それは本当に醜いでしょう。
PrintStreamを使用して、OutputStreamであるすべてに対してprintfを実行できます。どういうわけか、文字列ストリームに出力します:
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();
文字列ストリームは、次のByteArrayOutputStreamのように作成できます。
ByteArrayOutputStream baos = new ByteArrayOutputStream();