java.util.Formattable 上的示例是否不正确?
Is the sample on java.util.Formattable incorrect?
使用 example given for java.util.Formattable
(修改为在构造函数中实际设置值),事情似乎 大部分 正确:
import java.nio.CharBuffer;
import java.util.Formatter;
import java.util.Formattable;
import java.util.Locale;
import static java.util.FormattableFlags.*;
public class StockName implements Formattable {
private String symbol, companyName, frenchCompanyName;
public StockName(String symbol, String companyName,
String frenchCompanyName) {
this.symbol = symbol;
this.companyName = companyName;
this.frenchCompanyName = frenchCompanyName;
}
public void formatTo(Formatter fmt, int f, int width, int precision) {
StringBuilder sb = new StringBuilder();
// decide form of name
String name = companyName;
if (fmt.locale().equals(Locale.FRANCE))
name = frenchCompanyName;
boolean alternate = (f & ALTERNATE) == ALTERNATE;
boolean usesymbol = alternate || (precision != -1 && precision < 10);
String out = (usesymbol ? symbol : name);
// apply precision
if (precision == -1 || out.length() < precision) {
// write it all
sb.append(out);
} else {
sb.append(out.substring(0, precision - 1)).append('*');
}
// apply width and justification
int len = sb.length();
if (len < width)
for (int i = 0; i < width - len; i++)
if ((f & LEFT_JUSTIFY) == LEFT_JUSTIFY)
sb.append(' ');
else
sb.insert(0, ' ');
fmt.format(sb.toString());
}
public String toString() {
return String.format("%s - %s", symbol, companyName);
}
}
运行
System.out.printf("%s", new StockName("HUGE", "Huge Fruit, Inc.", "Fruit Titanesque, Inc."));
按预期打印 Huge Fruit, Inc.
。
但是,以下不起作用:
System.out.printf("%s", new StockName("PERC", "%Company, Inc.", "Fruit Titanesque, Inc."));
它抛出一个 java.util.MissingFormatArgumentException
:
Exception in thread "main" java.util.MissingFormatArgumentException: Format specifier '%C'
at java.util.Formatter.format(Formatter.java:2519)
at java.util.Formatter.format(Formatter.java:2455)
at StockName.formatTo(FormattableTest.java:44)
at java.util.Formatter$FormatSpecifier.printString(Formatter.java:2879)
at java.util.Formatter$FormatSpecifier.print(Formatter.java:2763)
at java.util.Formatter.format(Formatter.java:2520)
at java.io.PrintStream.format(PrintStream.java:970)
at java.io.PrintStream.printf(PrintStream.java:871)
at FormattableTest.main(FormattableTest.java:55)
示例使用 Formatter.format
添加文本,而 format
应该格式化格式字符串。当应该附加的文本包含百分比时,这会导致事情中断。
我应该如何在 formatTo
中处理这个问题? 我应该手动写入格式化程序的 Appendable (formatter.out().append(text)
,它可以抛出一个 IOException
不知何故)?我是否应该尝试转义格式字符串(类似于 formatter.format(text.replace("%","%%"))
,尽管这可能还不够)?我是否应该将一个简单的格式字符串传递给格式化程序(formatter.format("%s", text)
,但这似乎是多余的)?所有这些都应该有效,但语义上正确的方法是什么?
澄清一下,在这个假设的情况下,给StockName
的参数是用户控制的,可以是任意的;我无法完全控制它们(而且我不能禁止输入 %
)。但是,我可以编辑 StockName.formatTo
.
如果要打印百分号%,必须双写转义,例如
System.out.printf("%s", new StockName("PERC", "%%Company, Inc.", "Fruit Titanesque, Inc."));
这将打印 %Company, Inc.
其实很简单。您仅在格式化期间转义百分比字符,而不是在原始 属性:
// apply precision
if (precision == -1 || out.length() < precision) {
// write it all
sb.append(out.replaceAll("%", "%%"));
}
else {
sb.append(out.substring(0, precision - 1).replaceAll("%", "%%")).append('*');
}
那么如果你这样做:
StockName stockName = new StockName("HUGE", "%Huge Fruit, Inc.", "Fruit Titanesque, Inc.");
System.out.printf("%s%n", stockName);
System.out.printf("%s%n", stockName.toString());
System.out.printf("%#s%n", stockName);
System.out.printf("%-10.8s%n", stockName);
System.out.printf("%.12s%n", stockName);
System.out.printf(Locale.FRANCE, "%25s%n", stockName);
输出如下所示:
%Huge Fruit, Inc.
HUGE - %Huge Fruit, Inc.
HUGE
HUGE
%Huge Fruit*
Fruit Titanesque, Inc.
使用 example given for java.util.Formattable
(修改为在构造函数中实际设置值),事情似乎 大部分 正确:
import java.nio.CharBuffer; import java.util.Formatter; import java.util.Formattable; import java.util.Locale; import static java.util.FormattableFlags.*; public class StockName implements Formattable { private String symbol, companyName, frenchCompanyName; public StockName(String symbol, String companyName, String frenchCompanyName) { this.symbol = symbol; this.companyName = companyName; this.frenchCompanyName = frenchCompanyName; } public void formatTo(Formatter fmt, int f, int width, int precision) { StringBuilder sb = new StringBuilder(); // decide form of name String name = companyName; if (fmt.locale().equals(Locale.FRANCE)) name = frenchCompanyName; boolean alternate = (f & ALTERNATE) == ALTERNATE; boolean usesymbol = alternate || (precision != -1 && precision < 10); String out = (usesymbol ? symbol : name); // apply precision if (precision == -1 || out.length() < precision) { // write it all sb.append(out); } else { sb.append(out.substring(0, precision - 1)).append('*'); } // apply width and justification int len = sb.length(); if (len < width) for (int i = 0; i < width - len; i++) if ((f & LEFT_JUSTIFY) == LEFT_JUSTIFY) sb.append(' '); else sb.insert(0, ' '); fmt.format(sb.toString()); } public String toString() { return String.format("%s - %s", symbol, companyName); } }
运行
System.out.printf("%s", new StockName("HUGE", "Huge Fruit, Inc.", "Fruit Titanesque, Inc."));
按预期打印 Huge Fruit, Inc.
。
但是,以下不起作用:
System.out.printf("%s", new StockName("PERC", "%Company, Inc.", "Fruit Titanesque, Inc."));
它抛出一个 java.util.MissingFormatArgumentException
:
Exception in thread "main" java.util.MissingFormatArgumentException: Format specifier '%C'
at java.util.Formatter.format(Formatter.java:2519)
at java.util.Formatter.format(Formatter.java:2455)
at StockName.formatTo(FormattableTest.java:44)
at java.util.Formatter$FormatSpecifier.printString(Formatter.java:2879)
at java.util.Formatter$FormatSpecifier.print(Formatter.java:2763)
at java.util.Formatter.format(Formatter.java:2520)
at java.io.PrintStream.format(PrintStream.java:970)
at java.io.PrintStream.printf(PrintStream.java:871)
at FormattableTest.main(FormattableTest.java:55)
示例使用 Formatter.format
添加文本,而 format
应该格式化格式字符串。当应该附加的文本包含百分比时,这会导致事情中断。
我应该如何在 formatTo
中处理这个问题? 我应该手动写入格式化程序的 Appendable (formatter.out().append(text)
,它可以抛出一个 IOException
不知何故)?我是否应该尝试转义格式字符串(类似于 formatter.format(text.replace("%","%%"))
,尽管这可能还不够)?我是否应该将一个简单的格式字符串传递给格式化程序(formatter.format("%s", text)
,但这似乎是多余的)?所有这些都应该有效,但语义上正确的方法是什么?
澄清一下,在这个假设的情况下,给StockName
的参数是用户控制的,可以是任意的;我无法完全控制它们(而且我不能禁止输入 %
)。但是,我可以编辑 StockName.formatTo
.
如果要打印百分号%,必须双写转义,例如
System.out.printf("%s", new StockName("PERC", "%%Company, Inc.", "Fruit Titanesque, Inc."));
这将打印 %Company, Inc.
其实很简单。您仅在格式化期间转义百分比字符,而不是在原始 属性:
// apply precision
if (precision == -1 || out.length() < precision) {
// write it all
sb.append(out.replaceAll("%", "%%"));
}
else {
sb.append(out.substring(0, precision - 1).replaceAll("%", "%%")).append('*');
}
那么如果你这样做:
StockName stockName = new StockName("HUGE", "%Huge Fruit, Inc.", "Fruit Titanesque, Inc.");
System.out.printf("%s%n", stockName);
System.out.printf("%s%n", stockName.toString());
System.out.printf("%#s%n", stockName);
System.out.printf("%-10.8s%n", stockName);
System.out.printf("%.12s%n", stockName);
System.out.printf(Locale.FRANCE, "%25s%n", stockName);
输出如下所示:
%Huge Fruit, Inc.
HUGE - %Huge Fruit, Inc.
HUGE
HUGE
%Huge Fruit*
Fruit Titanesque, Inc.