Подтвердить что ты не робот

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

Интересно, почему 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)
}

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

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

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

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

public final String format(Date date)

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

Любые идеи?

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

На Java 5 появилось множество функций, но два примечания:

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

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

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

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

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

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

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

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

Ответ 6

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

  • питон:
    2.6: print "%s" % ("Hello")
    3.0: print("{0}".format("Hello"))
  • scala:
    2.7.6:   println("%s".format("Hello"))

Ответ 7

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

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

Ответ 8

Просто потому, что вызов напоминает функцию C sprintf.

Ответ 9

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

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

Ответ 10

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

Ответ 11

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

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

Ответ 12

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

Ответ 13

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

Ответ 14

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

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

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

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

а затем мы вызываем:

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

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

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

invalidFormat.format(anything);

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

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