2009-04-27 11 views
19

Zastanawiam się dlaczego Java 5 i powyżej stanowią formatowania printf stylu przy użyciu statycznej metody w klasie String tak:Dlaczego format String (Object ... args) jest zdefiniowany jako metoda statyczna?

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

zamiast

public String format(Object... args) 

tak, że możemy napisać "%02d".format(5) do uzyskać 05 zamiast String.format("%02d", 5).

Wyobrażałem sobie, gdybym mógł modyfikować klasy String, mogę dodać to:

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

aby uzyskać ten sam rezultat.

Znalazłem, że w C#, metoda statyczna jest również używana zamiast metody instancji.

Zastanawiam się, dlaczego zdecydowali się to zrobić, ale nie znalazłem wyjaśnienia. Metody instancji trim i substring zwracają nową instancję ciągu, więc powinny zrobić to samo z format.

Ponadto klasa DateFormat wykorzystuje to również:

public final String format(Date date) 

formatowania dat. Więc jeśli weźmiemy pod uwagę instancję DateFormat jako formatera, instancja String może być również używana jako formater.

Wszelkie pomysły?

+0

czy to naprawdę ma znaczenie? –

+0

to naprawdę nie ma znaczenia, ale ja właśnie zastanawiam się, czy istnieje jakiekolwiek uzasadnienie tego. Ponieważ nie piszemy "String.substring (" abcde ", 3, 2)' ale '" abcde ".substring (3, 2)', format powinien również mieć podobną metodę wywołania, jak sądzę. – yuku

+2

Podobnie, dlaczego jest to 'Collections.sort (List)', a nie 'List.sort()'. Nigdy nie lubiłem tak bardzo. – skaffman

Odpowiedz

9

Być może "%02d".format(5) wydaje się sugerować, że obiekt, na który jest wywoływana metoda format, jest ciągiem formatującym.

W tym przypadku ciąg formatu bywa również String, więc wspierając tym momencie jeden mógłby argumentować, że wszystkie String s to jest format ciągów.

Prawdopodobnie można tego uniknąć, mówiąc, że statyczna metoda w klasie String może być użyta do sformatowania ciągu znaków, zamiast generować jakieś domyślne oświadczenie o wszystkich ogólnie dostępnych String s.

+0

To wydaje się rozsądnym punktem. –

+0

To prawda, dziękuję za to! To przypomina mi publiczne dopasowania boolowskie (String regex), które ma podobny wzór do tego. – yuku

6

Głównym powodem jest prawdopodobnie to, że projektanci Javy nie chcieli dodawać zbyt wiele rzeczy do interfejsu String. Uczynienie go funkcją członka oznaczałoby wprowadzenie go na sznurku. Pamiętaj, że metoda niestatyczna musiałaby znajdować się w obiekcie String.

Drugim powodem jest to, że format statyczny podtrzymuje swoje podobieństwo do printf C, w który wygląda jak printf (format, arg1, arg2 ...)

Innym powodem jest to, że format jest przeciążony: istnieje wersja który bierze locale jako pierwszy parametr (przed ciągiem), więc zrobienie tego na obiekcie typu string byłoby trudne.

0

Być może, aby pokazać, że jest to funkcja "użyteczności", która istnieje dla wygody, ale która tak naprawdę nie jest wewnętrzną funkcją ciągu. Oznacza to, że String "%02d" jest sposobem reprezentowania formatu, ale w rzeczywistości nie wykonuje żadnego formatowania.

Metoda służy do wygodnego formatowania ciągów znaków, ale Formatter (która wykonuje faktyczne formatowanie) może również formatować inne typy obiektów (data itp.).

3

"% 02d" .format (5) wyglądałby "% 02d" jest sformatowany przy użyciu formatu 5, a nie odwrotnie. Również większość ciągów znaków nie nadaje się jako format ("hello world" .format (5)?), Więc metoda powinna generować wyjątki dla większości obiektów typu string.

-1

W języku C#, strings are immutable. Myślę, że to jest prawdą również w Javie (nie jest to w 100% pewne). Więc nie zmieniasz łańcucha, wywołując na nim metodę formatowania, zwracasz tylko nowy ciąg z formatowaniem. To sprawia, że ​​jest to metoda na poziomie klasy, a nie metoda na poziomie instancji, dlatego jest statyczna. Możesz dodać elewację poziomu instancji w języku C#, używając funkcji rozszerzenia, ale jest to po prostu cukier syntaktyczny na wierzchu funkcji statycznej.

+0

Masz rację, to samo dotyczy również napisu Java. – arul

+1

-1, ponieważ można to powiedzieć o każdej funkcji klasy ciągów, a nie tylko o formacie. – Samuel

+0

Nie obwiniaj mnie. Większość metod na łańcuchu (przynajmniej w C#) nie implikuje żadnej mutacji. Te, które implikują mutację, wszystkie zwracają ciąg. Ale w przypadku formatu jest bardzo jasne, że nie ma powodu, aby zmuszać cię do tworzenia ciągu znaków. –

3

Odpowiedź dotyczy metody Format.

Jest bardziej logiczne i intuicyjne, przynajmniej dla mnie, stwierdzenie, że "ciąg formatu jest wprowadzany do metody formatowania" niż stwierdzenie, że "Format działa na łańcuchu formatującym". Jest tak, ponieważ "zazwyczaj" przekazujemy formatowanie, znane w czasie projektowania, do formatu. W przeciwieństwie do Trim, "zwykle" przekazujemy ciąg zmienny, którego wartość nie jest znana w czasie projektowania.

Dzięki czemu formatowanie jest statyczne, dzięki czemu odczyt kodu staje się bardziej intuicyjny. Spójrz na następujące (C#).

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

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

EDYCJA: Mimo że użyłem przykładowy kod C#, ma on również zastosowanie do Java. Mam -ve głosować za używanie składni C#!

+1

Jest to jednak pytanie Java. Prawdopodobnie pomoże to w użyciu składni Java na przykładzie C#. – dlamblin

+0

Witam, dlamblin Chociaż jest oznaczony jako pytanie Java, to również odnosi się do C#, jak zauważył przez pytającego. Myślę, że nieuczciwe jest obniżanie reputacji jako mojej odpowiedzi (prosimy o przeczytanie fragmentu tekstu przed zapoznaniem się z moim przykładowym kodem) dotyczy również Javy! Proszę o usunięcie negatywnego głosowania. – isntn

+0

Dzięki, Dlamblin. – isntn

1

Tylko dlatego, że połączenie przypomina funkcję C sprintf.

0

Prawdopodobnie dlatego, że String jest niezmienny i dlatego ta metoda musi utworzyć i zwrócić nową instancję instancji String. Jeśli metoda nie została zadeklarowana jako statyczna, prawdopodobnie oczekuje się, że zmodyfikuje instancję String, na którą została wywołana.

-1

Myślę, że nie jest konieczne, aby Java tworzyła jakikolwiek konstrukt podobny do czegokolwiek innego, nawet C++. Wszystko to musi być przyjęte, ponieważ programiści ją akceptują. Poza tym argumenty takie jak "uczyniły to podobnym do czegoś innego" nie wyjaśniają, dlaczego nie tworzą wersji metody instancji, robią to z prymitywnymi owijkami (oprócz metody toString(), mają wersję statyczną).

To jest to, co myślę:

W normalnym przypadku, obie formy są równoważne, ale załóżmy, że mamy coś takiego:

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

a następnie nazywamy:

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

niepoprawny staje się argumentem, a Javy to wyjaśnia, rzucając wystąpienie IllegalArgumentException (nawet w przypadku Formattera istnieje wiele rodzajów).

Jednak w coś takiego:

invalidFormat.format(anything); 

nieważne nikt już nie jest argument.Problem dotyczy teraz instancji, do której jest wywoływany i dlatego jest lepiej opisany jako "nieprawidłowy stan" (nie "IllegalStateException" języka Java, który ma zupełnie inne zastosowanie). Ponieważ jednak ciągi znaków są niezmienne, tak zwany "stan" nigdy się nie zmieni, więc zawsze pozostanie nieprawidłowy jako format, mimo że jest to poprawny prosty ciąg.

Porównaj to z, powiedzmy, java.lang.Long. Obie wersje toString nigdy nie wyrzucą żadnego wyjątku, więc oba są równoważne.

+0

Dlaczego więc nie zmienić 'java.util.IllegalFormatException', aby nie rozszerzać' java.lang.IllegalArgumentException', ale raczej być własną, niezależną klasą? Myślę, że byłoby sensownym powiedzieć ciągowi znaków, aby sformatował się przez wstawienie obiektów, ale potem zwrócił błąd, że ciąg nie był prawidłowym formatem. –

7

Chociaż nie jestem projektantem Javy, mogę podać jeden wyraźny powód, dla którego jest on statyczny.

Java 5 wyszedł z wieloma funkcjami, ale dwie noty były:

  • Zdolność do wykonywania „import static” polecenia, które pozwoliły metody statyczne być stosowane od wewnątrz klasy łatwo i bez wystawianie ich klasę Nazwa.
  • Statyczna metoda użyteczności, która w prosty sposób wykonała printfs.

Chociaż byłoby miło móc powiedzieć "bla: %d".format("foo"), poprzez metodę statyczną można użyć formatu w sposób, który jest bardzo znany i czyste wyglądające dla programistów C używany do printf().

import static java.lang.String.format; 

public class Demo { 

    public void Test() { 

     //Do some stuff 

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

    } 
} 

I dlatego! Korzystając z importu statycznego, printfs wyglądają prawie tak, jak w C. Świetne!

+0

Nice! Nie myślałem o tym. Chociaż myślę, że to, co chcesz powiedzieć, to java.lang.String.format nie java.lang.String.printf;) – yuku

+0

Tak, byłem trochę zmęczony, kiedy to napisałem. Naprawiono :) –

2

Wywołanie strfmt.format (obiektów) zamiast string.Format (strfmt, obiekty)

  • jest zorientowane obiektowo wezwanie zamiast zaproszenia do statycznego pomocnika.
  • krótszy typ.
  • jest prostszy, ponieważ ma mniej argumentów.
  • jest łatwiejszy w użyciu z uzupełnianiem kodu. Jeśli zaczynasz od ciągu formatu i naciśnij. otrzymujesz format () jako opcję w IDE.
  • String.format (strfmt, objects) może być przypadkowo nazywany jako strfmt.format (tekst, obiekty), który nie zrobiłby tego, co wydaje się robić.
+4

Jak ta odpowiedź na pytanie? –

3

naprawdę myślę format musi być metoda instancji String i tak też zrobić

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

A w Javie: System.out.printf ("% s% n", "Hello"); Używam printf() przez większość czasu zamiast String.format(). –

+0

Jak to odpowiada na pytanie? – DerMike

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

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

Po prostu kiepski projekt. Pythoner uważa to za bolesne.

Powiązane problemy