Используя пример, приведенный для 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
.