Эквивалент Sprintf в Java - PullRequest
       14

Эквивалент Sprintf в Java

270 голосов
/ 06 сентября 2008

Printf был добавлен в Java с выпуском 1.5, но я не могу найти, как отправить вывод в строку, а не в файл (что и делает sprintf в C). Кто-нибудь знает как это сделать?

Ответы [ 3 ]

456 голосов
/ 06 сентября 2008
// Store the formatted string in 'result'
String result = String.format("%4d", i * j);

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

См. формат и его синтаксис

25 голосов
/ 13 октября 2008

@erickson.

Строки являются неизменяемыми типами. Вы не можете изменять их, только возвращать новые экземпляры строк.

Из-за этого "foo" .format () не имеет большого смысла, так как он должен быть вызван как

string newString = "foo".format();

Первоначальные авторы java (и авторы .NET) решили, что статический метод имеет больше смысла в этой ситуации, поскольку вы не изменяете "foo", а вместо этого вызываете метод форматирования и передаете входную строку.

РЕДАКТИРОВАТЬ : Хех, этот сайт иногда может быть настолько забавным. Меня опровергли за упоминание того факта, что строки являются неизменяемыми типами.

Вот пример того, почему Format () будет глупым как метод экземпляра. В .NET (и, вероятно, в Java) Replace () является методом экземпляра.

Вы можете сделать это:

 "I Like Wine".Replace("Wine","Beer");

Однако ничего не происходит, потому что строки неизменны. Replace пытается вернуть новую строку, но ей ничего не назначено.

Это вызывает много распространенных ошибок новичка, таких как:

// Contrived Example
inputText.Replace(" ","%20");

Опять ничего не происходит, вместо этого вы должны сделать:

inputText = inputText.Replace(" ","%20");

Теперь, если вы понимаете, что строки неизменны, это имеет смысл. Если вы этого не сделаете, то вы просто запутались. Правильное место для Replace, где будет Format, как статический метод String:

 inputText = String.Replace(inputText," ", "%20");

Теперь нет никаких сомнений относительно того, что происходит.

Реальный вопрос в том, почему авторы этих фреймворков решили, что один должен быть методом экземпляра, а другой - статическим? На мой взгляд, оба более элегантно выражены как статические методы, но Эриксон, кажется, считает, что оба принадлежат как методы экземпляра.

Независимо от вашего мнения, правда в том, что вы менее склонны ошибаться при использовании статической версии, а код легче понять (без скрытых ошибок).

Конечно, есть некоторые методы, которые идеально подходят в качестве методов экземпляра, возьмите String.Length ()

int length = "123".Length();

В этой ситуации очевидно, что мы не пытаемся изменить «123», мы просто проверяем его и возвращаем его длину ... Это идеальный кандидат для метода экземпляра.

Мои простые правила для методов экземпляров для неизменяемых объектов:

  • Если вам нужно вернуть новый экземпляр того же типа, используйте статический метод.
  • В противном случае используйте метод экземпляра.
2 голосов
/ 14 июля 2015

Оба решения работают для имитации 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)));
    ...
    

... но это было бы действительно безобразно.

...