Эквивалент Sprintf на Java
-
09-06-2019 - |
Вопрос
Printf был добавлен в Java с версией 1.5, но я не могу найти, как отправить вывод в строку, а не в файл (что и делает sprintf в C).Кто-нибудь знает как это сделать?
Другие советы
@erickson.
Строки являются неизменяемыми типами.Вы не можете их изменять, а возвращать только новые экземпляры строк.
Из-за этого «foo.format()» не имеет смысла, так как его нужно было бы называть так:
string newString = "foo".format();
Первоначальные авторы Java (и авторы .NET) решили, что статический метод имеет больше смысла в этой ситуации, поскольку вы не изменяете «foo», а вместо этого вызываете метод форматирования и передаете входную строку.
РЕДАКТИРОВАТЬ:Хех, этот сайт иногда может быть таким забавным.Меня проголосовали против за упоминание того факта, что строки являются неизменяемыми типами.
Вот пример того, почему Format() был бы глупым в качестве метода экземпляра.В .NET (и, возможно, в Java) replace() является методом экземпляра.
Вы можете сделать это:
"I Like Wine".Replace("Wine","Beer");
Однако ничего не происходит, поскольку строки неизменяемы.Заменить пытается вернуть новую строку, но ей ничего не присвоено.
Это приводит к множеству распространенных ошибок новичков, таких как:
// Contrived Example
inputText.Replace(" ","%20");
Опять ничего не происходит, вместо этого вам нужно сделать:
inputText = inputText.Replace(" ","%20");
Теперь, если вы понимаете, что строки неизменяемы, это имеет смысл.Если нет, то вы просто запутались.Подходящим местом для замены будет то место, где находится формат, как статический метод 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))); ...
Существует третье решение, заключающееся в простом добавлении символа в
ret
один за другим (символы — это числа, которые добавить друг к другу!), например:... ret += HexChars.charAt((int) ((v >> 12) & 0x0f))); ret += HexChars.charAt((int) ((v >> 8) & 0x0f))); ...
...но это было бы Действительно уродливый.