Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/367.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的Sprintf等价物_Java_String_Formatting - Fatal编程技术网

Java中的Sprintf等价物

Java中的Sprintf等价物,java,string,formatting,Java,String,Formatting,Printf是在1.5版本中添加到Java的,但我似乎找不到如何将输出发送到字符串而不是文件(这是sprintf在C中所做的)。有人知道怎么做吗 // Store the formatted string in 'result' String result = String.format("%4d", i * j); // Write the result to standard output System.out.println( result ); 请参阅及其字符串是不可变的类型。您不能

Printf是在1.5版本中添加到Java的,但我似乎找不到如何将输出发送到字符串而不是文件(这是sprintf在C中所做的)。有人知道怎么做吗

// Store the formatted string in 'result'
String result = String.format("%4d", i * j);

// Write the result to standard output
System.out.println( result );

请参阅及其

字符串是不可变的类型。您不能修改它们,只能返回新的字符串实例

因此,使用实例方法进行格式化没有什么意义,因为必须像以下那样调用它:

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()为例

在这种情况下,很明显我们并没有试图修改“123”,我们只是检查它,并返回它的长度。这是实例方法的完美候选

我对不可变对象上的实例方法的简单规则:

  • 如果需要返回相同类型的新实例,请使用静态方法
  • 否则,请使用实例方法

两种解决方案都可以模拟printf,但方式不同。 例如,要将值转换为十六进制字符串,有以下两种解决方案:

  • 使用
    format()
    ,最接近
    sprintf()

  • 使用
    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)));
        ...
    
  • 第三种解决方案是将字符逐个添加到
    ret
    (字符是相互添加的数字!),例如:

    ...
    ret += HexChars.charAt((int) ((v >> 12) & 0x0f)));
    ret += HexChars.charAt((int) ((v >>  8) & 0x0f)));
    ...
    

…但那真的很难看。

你可以对任何输出流进行printf。 不知何故,打印到字符串流中:

PrintStream ps = new PrintStream(baos);
ps.printf("there is a %s from %d %s", "hello", 3, "friends");
System.out.println(baos.toString());
这将输出以下文本来自3个朋友的问候 字符串流可以通过以下方式创建:ByteArrayOutputStream:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
您可以累积多种格式:

PrintStream ps = new PrintStream(baos);
ps.printf("there is a %s from %d %s ", "hello", 3, "friends");
ps.printf("there are %d % from a %", 2, "kisses", "girl");
System.out.println(baos.toString());
这输出有3个朋友的问候有2个女孩的亲吻
调用ByteArrayOutputStream上的reset以生成干净的新字符串

ps.printf("there is a %s from %d %s", "flip", 5, "haters");
baos.reset(); //need reset to write new string
ps.printf("there are %d % from a %", 2, "kisses", "girl");
System.out.println(baos.toString());

输出将是有两个女孩的吻

自从Java 13以来,您在字符串上设置了
格式的
方法,该方法与文本块一起作为预览功能添加。 您可以使用它代替
String.format()

Assertions.assertEquals(
“%s%d%.3f”。格式化(“foo”,123,7.89),
“foo 123 7.890”
);

我看到您不知怎么地想到了我建议修改格式字符串的想法。我从来没有考虑过有人会期望字符串发生变化的可能性,因为它们的不变性是非常基本的。由于格式字符串通常更像“价格是%4d”,而不是“%4d”,我仍然认为有很多可能引起混淆。您对静态方法有什么看法?:)这个答案似乎与这个问题无关。答案甚至不是Java,似乎与.NET-1更相关。降票b/c,这是切向的。不一定是不可变的最佳样式。这种风格比简单的方法调用更冗长,尤其是对于链式操作。它放弃了运行时多态性,因为它调用了静态方法,这很重要。所有这些都是好主意,但是把你的代码变成了你的同事无法理解的只写代码。
PrintStream ps = new PrintStream(baos);
ps.printf("there is a %s from %d %s ", "hello", 3, "friends");
ps.printf("there are %d % from a %", 2, "kisses", "girl");
System.out.println(baos.toString());
ps.printf("there is a %s from %d %s", "flip", 5, "haters");
baos.reset(); //need reset to write new string
ps.printf("there are %d % from a %", 2, "kisses", "girl");
System.out.println(baos.toString());