Почему формат String (Object... args) определяется как статический метод?

интересно, почему Java 5 и выше обеспечивают форматирование в стиле printf, используя статический метод в строке класса, как это:

public static String format(String format, Object... args)

вместо

public String format(Object... args)

чтобы мы могли писать "%02d".format(5) и 05 вместо String.format("%02d", 5).

Я представил, что если бы я мог изменить класс String, я мог бы добавить это:

public String format(Object... args) {
    return format(this, args)
}

чтобы получить тот же результат.

я обнаружил, что в C# вместо статического метода также используется метод экземпляра.

14 ответов


возможно "%02d".format(5) кажется, подразумевает, что объект, на который format вызывается метод-это строка формата.

в этом случае строка формата также является String, так продвигая эту точку,можно утверждать, что все Stringстрока формат.

наверное, этого можно избежать, сказав, что статический метод в String класс может использоваться для форматирования строки, а не для создания некоторого неявного утверждения обо всех Strings в генеральный.


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

Java 5 вышел со многими функциями, но два из них были:

  • возможность выполнять команды "import static", которые позволяют использовать статические методы из класса легко и без перечисления их имени класса.
  • статический метод утилиты, который легко выполнял printfs.

хотя было бы неплохо иметь возможность сказать "bla: %d".format("foo"), by делая метод статическим, вы можете использовать формат таким образом, чтобы он был очень знакомым и чистым для программистов C, используемых для printf().

import static java.lang.String.format;

public class Demo {

   public void Test() {

      //Do some stuff

      format("Hey, this is easy to read!");

   }
 }

и вот почему! Используя статический импорт, printfs выглядят почти так же, как в C. Awesome!


основная причина, вероятно, в том, что дизайнеры Java не хотели добавлять слишком много материала в интерфейс String. Сделать его функцией-членом означало бы поместить его в строку. Помните,что нестатический метод должен быть на объекте String.

вторая причина заключается в том, что статический формат сохраняет сходство с printf C, который выглядит как printf (FORMAT, ARG1, ARG2...)

другая причина в том, что формат перегружен: есть версия это принимает locale в качестве первого параметра (перед строкой), поэтому сделать это на объекте string было бы сложно.


"%02d порта".формат (5) будет выглядеть как "%02d" отформатирован с использованием формата 5, а не наоборот. Также большинство строк не подходят в качестве формата ("hello world".формат(5)?), поэтому метод должен создавать исключения для большинства строковых объектов.


ответ лежит в ответственности метода Format.

более логично и интуитивно, по крайней мере для меня, сказать, что "строка формата вводится в метод форматирования", чем сказать, что "формат работает с строкой формата". Это так, как мы" обычно " передаем строку формата, известную во время разработки, в формат. Напротив, для Trim мы" обычно " передаем переменную string, значение которой не известно во время разработки.

Итак, делая метод формата статическим, сделайте чтение кода более интуитивным. Посмотрите на следующее (C#).

answer = String.Format("This is format string : {0}", someValue); 
//More readable to me

answer = "This is format string : {0}".Format(someValue);

EDIT: хотя я использовал пример кода C#, он хорошо применяется к Java. Я получил-ve голос за использование синтаксиса C#!


Я думаю format должен быть методом экземпляра String, а также

  • python:
    2.6: print "%s" % ("Hello")
    3.0: print("{0}".format("Hello"))
  • scala:
    2.7.6:   println("%s".format("Hello"))

вызов strfmt.формат (объекты) вместо строки.format (strfmt, objects)

  • является объектно-ориентированным вызовом вызова статического помощника.
  • его короче тип.
  • его проще, так как он имеет на один аргумент меньше.
  • его проще использовать автозавершение кода. Если вы начинаете с отформатируйте строку и нажмите . вы получаете format () в качестве опции в IDE.
  • строку.формат (strfmt, objects) может быть случайным как strfmt.формат (текст, объекты), который не сделал бы того, что кажется.

просто потому, что вызов напоминает C's .


возможно, чтобы показать, что это функция" полезности", которая существует для удобства, но которая на самом деле не является внутренней функцией строки. То есть строка "%02d" - Это способ представления формата, но на самом деле он не выполняет форматирование.

метод существует для удобного форматирования строк, но форматер (который выполняет фактическое форматирование) также может форматировать другие типы объектов (дата и т. д.).


вероятно, потому что String неизменяема, и поэтому этот метод должен создать и вернуть новый экземпляр экземпляра String. Если метод не был объявлен статическим, можно ожидать, что он изменит экземпляр String, на котором он был вызван.


Я думаю, что не обязательно, чтобы Java делала любую конструкцию похожей на что-либо еще, даже на C++. Все, что принято, должно быть так, потому что разработчики принимают это. Кроме того, такие аргументы, как "они сделали его похожим на что-то еще", не объясняют, почему они не просто делают версию метода экземпляра, они делают это с примитивными оболочками (в дополнение к методу экземпляра toString (), у них есть статическая версия).

вот что я думаю:

в обычном случае обе формы эквивалентны, но предположим, что у нас есть что-то вроде:

String invalidFormat = "%invalid"; // or something else that is invalid

и тогда мы называем:

String.format(invalidFormat, anything);
// "anything" is indeed anything....

недопустимым становится аргумент, и Java проясняет это, бросая экземпляр IllegalArgumentException (даже в случае форматирования существует много видов).

однако, в чем-то вроде:

invalidFormat.format(anything);

недействительной не аргумент. Проблема сейчас лежит экземпляр его называют и так проребенок лучше назвать "недопустимое состояние "(не" IllegalStateException " Java, которое имеет совершенно другое использование). Но поскольку строки неизменяемы, это так называемое "состояние" никогда не изменится, поэтому оно всегда будет оставаться недействительным как формат, даже если это допустимая простая строка.

сравните это, скажем, с java.ленг.Длинный. Обе версии toString никогда не будут создавать никаких исключений, поэтому они оба эквивалентны.


answer = String.Format("This is format string : {0}", someValue); 
//More readable to me

answer = "This is format string : {0}".Format(someValue);

просто плохой дизайн. Прорицатель находит это болезненным.


В C#строки являются неизменяемыми. Я думаю, что это верно и в Java (не на 100% уверен в этом). Таким образом, вы не изменяете строку, вызывая метод format на ней, вы только возвращаете новую строку с форматированием. Это делает его методом уровня класса, а не методом уровня экземпляра, поэтому он статичен. Вы можете добавить фасад уровня экземпляра в C#, используя функцию расширения, но это просто синтаксический сахар поверх статической функции.