Answers:
字符串是不可变的类型。您不能修改它们,只能返回新的字符串实例。
因此,使用实例方法进行格式化几乎没有意义,因为必须像这样调用它:
String formatted = "%s: %s".format(key, value);
最初的Java作者(和.NET作者)认为,在这种情况下,静态方法更有意义,因为您不是在修改目标,而是调用format方法并传入输入字符串。
这是一个为什么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");
现在毫无疑问发生了什么。
真正的问题是,这些框架的作者为什么决定一个应该是实例方法,而另一个应该是静态方法呢?我认为,这两种方法都可以更好地表达为静态方法。
不管您的意见如何,事实是,使用静态版本时您不太容易犯错误,并且代码更易于理解(没有隐藏的陷阱)。
当然,有些方法是完美的实例方法,例如String.Length()
int length = "123".Length();
在这种情况下,很明显我们没有试图修改“ 123”,我们只是在检查它并返回它的长度。这是实例方法的理想选择。
我对不可变对象的实例方法的简单规则:
两种解决方案都可以模拟printf,但是方式不同。例如,要将值转换为十六进制字符串,您有以下两种解决方案:
与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
逐个加(char是互相加成的数字!),例如:
...
ret += HexChars.charAt((int) ((v >> 12) & 0x0f)));
ret += HexChars.charAt((int) ((v >> 8) & 0x0f)));
...
...但是那真的很丑。
您可以对带有PrintStream的OutputStream进行任何处理。像这样,打印到字符串流中:
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();