Printf был добавлен в Java с выпуском 1.5, но я не могу найти, как отправить вывод в строку, а не в файл (что делает sprintf в C). Кто-нибудь знает как это сделать?
Printf был добавлен в Java с выпуском 1.5, но я не могу найти, как отправить вывод в строку, а не в файл (что делает 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()
был бы глуп как метод экземпляра. В .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, но по-разному. Например, чтобы преобразовать значение в шестнадцатеричную строку, у вас есть 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)));
...
Существует третье решение, состоящее в том, чтобы просто добавлять символ ret
один за другим (символы - это числа, которые дополняют друг друга !), Например:
...
ret += HexChars.charAt((int) ((v >> 12) & 0x0f)));
ret += HexChars.charAt((int) ((v >> 8) & 0x0f)));
...
... но это было бы действительно ужасно
Вы можете сделать printf для всего, что является OutputStream с PrintStream. Как-то так, печать в поток строки:
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();