Почему формат String (Object ... args) определяется как статический метод? - PullRequest
22 голосов
/ 27 апреля 2009

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

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 # вместо метода экземпляра также используется статический метод.

Интересно, почему они решили это сделать, но я не пришел к объяснению. Методы экземпляра trim и substring возвращают новый экземпляр строки, поэтому они должны были сделать то же самое с format.

Кроме того, класс DateFormat также использует это:

public final String format(Date date)

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

Есть идеи?

Ответы [ 14 ]

11 голосов
/ 27 апреля 2009

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

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

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

7 голосов
/ 27 апреля 2009

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

Java 5 вышла с множеством функций, но две заметки были:

  • Возможность выполнения команд «импорта статических», позволяющих легко использовать статические методы внутри класса и без указания имени класса.
  • Статический служебный метод, который легко выполняет printfs.

Хотя было бы неплохо иметь возможность сказать "bla: %d".format("foo"),, сделав метод статичным, вы можете использовать форматирование таким способом, который очень знаком и понятен программистам на 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. Удивительно!

5 голосов
/ 27 апреля 2009

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

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

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

3 голосов
/ 27 апреля 2009

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

Более логично и интуитивно понятно, по крайней мере для меня, сказать, что «строка формата является входом для метода Форматирования», чем сказать, что «Формат работает на строке формата». Это так, поскольку мы «обычно» передаем форматированную строку, известную во время разработки, в Format. Напротив, для Trim мы «обычно» передаем переменную строку, значение которой неизвестно во время разработки.

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

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

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

РЕДАКТИРОВАТЬ: Несмотря на то, что я использовал пример кода C #, он хорошо подходит для Java. Я получил -ve голос за использование синтаксиса C #!

3 голосов
/ 27 апреля 2009

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

2 голосов
/ 17 января 2010

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

  • питон:
    2.6: print "%s" % ("Hello")
    3.0: print("{0}".format("Hello"))
  • Скала:
    2.7.6:   println("%s".format("Hello"))
1 голос
/ 28 апреля 2009

Вызов strfmt.format (объекты) вместо String.format (strfmt, объекты)

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

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

0 голосов
/ 12 марта 2011
answer = String.Format("This is format string : {0}", someValue); 
//More readable to me

answer = "This is format string : {0}".Format(someValue);
0 голосов
/ 27 апреля 2009

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

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

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

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

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

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

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

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

invalidFormat.format(anything);

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

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

...