Integer.toString (int i) vs String.valueOf (int i)


176

Zastanawiam się, dlaczego String.valueOf(int i)istnieje metoda ? Używam tej metody, aby przekształcić intsię Stringi właśnie odkrył Integer.toString(int i)metodę.

Po przejrzeniu implementacji tych metod zobaczyłem, że pierwsza wywołuje drugą. W konsekwencji wszystkie moje wezwania String.valueOf(int i)dotyczą jednego połączenia więcej niż bezpośredniegoInteger.toString(int i)


Odpowiedzi:


46

Tylko dwa różne sposoby na zrobienie tego samego. Może to być powód historyczny (nie pamiętam, czy jeden był przed drugim).


22
Tak, ale jeśli coś robi to samo, nie oznacza, że ​​to to samo.
Damian Leszczyński - Vash

3
String.valueOf (int) po prostu wywołuje bezpośrednio Integer.toString (i). Dlatego najlepiej wywołać Integer.toString (int).
djchapm

171

W typie String mamy kilka metod valueOf

static String   valueOf(boolean b) 
static String   valueOf(char c) 
static String   valueOf(char[] data) 
static String   valueOf(char[] data, int offset, int count) 
static String   valueOf(double d) 
static String   valueOf(float f) 
static String   valueOf(int i) 
static String   valueOf(long l) 
static String   valueOf(Object obj) 

Jak widzimy, ta metoda jest w stanie rozwiązać wszystkie rodzaje liczb

każda implementacja określonej metody, jaką przedstawiłeś: Więc dla liczb całkowitych mamy

Integer.toString(int i)

za podwójne

Double.toString(double d)

i tak dalej

Moim zdaniem nie jest to kwestia historyczna, ale dla programisty bardziej przydatne jest użycie metody valueOfz klasy String niż z odpowiedniego typu, ponieważ prowadzi to do mniejszej liczby zmian, które możemy wprowadzić.

Próbka 1:

public String doStuff(int num) {

  // Do something with num...

  return String.valueOf(num);

 }

Próbka2:

public String doStuff(int num) {

 // Do something with num...

 return Integer.toString(num);

 }

Jak widzimy w próbce 2, musimy dokonać dwóch zmian, w przeciwieństwie do próbki pierwszej.

Podsumowując, użycie valueOfmetody z klasy String jest bardziej elastyczne i dlatego jest tam dostępne.


18
I nie zapominaj, Integer.toString(int i, int radix)że zamieni się na łańcuchy zasad inne niż 10.
Stephen P

@Vash Czy mógłbyś również wyjaśnić, jak używać pustego ciągu do konwersji int na String w porównaniu do String.valueOf? np.) „” + int i = „i”? Który jest najlepszy?
Kanagavelu Sugumar

1
Aby sformatować int jako łańcuch, nie powinieneś używać "" + i. Nie ma dużych nad głową, ale generalnie dlatego, że nie jest to eleganckie. Zamiast używać String.valueOf(int), możesz użyć, String.format("%d",i);aby przeczytać więcej, odwiedź tę stronę internetową docs.oracle.com/javase/6/docs/api/java/util/Formatter.html
Damian Leszczyński - Vash

Chciałbym, żeby autoboxing był sprytniejszy i po prostu dodałem konwersję na kompilacji czy coś.
Rob Grant

1
@RobertGrant Autoboxing nie ma tutaj miejsca. Ale aby odpowiedzieć na twoje obawy, jest to sprytne, ponieważ możesz to zrobić int i = new Integer("1");i odwrotnie.
Damian Leszczyński - Vash

52

Jedną ogromną różnicą jest to, że jeśli wywołasz toString()obiekt o wartości null, otrzymasz a NullPointerException, a używając String.valueOf()możesz nie sprawdzać wartości null.


46
Pytanie jest o Integer.toString(int i), A staticmetoda. Nie ma nullobiektów możliwych.
Petr Janeček

14
Integer i = null; i.toString(); // Null pointer exception!! String.valueOf(i); // No exception
manish_s

10
@Manis Kumar: Twój przykład nie uruchomi String.valueOf(int i)metody, ale String.valueOf(Object obj). W każdym razie pytanie dotyczy prymitywnych intwartości, których nie ma null.
hleinone

1
@manish_s z przykładu jasno wynikało, że nikt nie mówi o typie obiektu Integer. Mówimy tylko o prymitywach.
Daniel Ochoa

2
@manish_s: OP nie powiedział, Integer.toString()ale Integer.toString(int i). To jest metoda statyczna ( docs.oracle.com/javase/7/docs/api/java/lang/… ).
LarsH

13

Klasa String zapewnia metody valueOf dla wszystkich typów pierwotnych i typu Object, więc zakładam, że są to wygodne metody, do których można uzyskać dostęp za pośrednictwem jednej klasy.

NB Wyniki profilowania

Średnia intToString = 5368 ms, średnia stringValueOf = 5689 ms (dla 100 000 000 operacji)

public class StringIntTest {


    public static long intToString () {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            String j = Integer.toString(i);
        }
        long finishTime = System.currentTimeMillis();

        return finishTime - startTime;
    }

    public static long stringValueOf () {

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            String j = String.valueOf(i);
        }
        long finishTime = System.currentTimeMillis();

        return finishTime - startTime;
    }

    public static void main(String[] args) {
        long intToStringElapsed = 0;
        long stringValueOfElapsed = 0;
        for (int i = 0; i < 10; i++) {
            intToStringElapsed += intToString();
            stringValueOfElapsed+= stringValueOf();
        }
        System.out.println("Average intToString = "+ (intToStringElapsed /10));
        System.out.println("Average stringValueOf = " +(stringValueOfElapsed / 10));
    }
}

7
Twoje profilowanie powinno naprawdę mieć okres „rozgrzewki”, w przeciwnym razie wyniki mogą zostać wypaczone przez majsterkowanie JIT. To powiedziawszy, różnica 300 ms w 10 ^ 8 operacjach jest tak mała, że ​​jest całkowicie pomijalna.
Cameron Skinner

1
@Kingo Nie sądzę, że twój przypadek testowy jest poprawny. Ponieważ przypisujesz wartość, String jale nigdy jej nie używasz. Bazowy kompilator mógł to zoptymalizować. Lepiej jest przekazać obiekt j inną metodą i wykonać fikcyjną operację.
Rakesh

1
Naprawdę nie powinieneś w ten sposób pisać domowych mikro testów porównawczych. Jeśli używasz JMH . Zajmie się rozgrzewką, pomiarem czasu, wieloma niezależnymi próbami (forks Java!) I sprawi, że kod będzie mały, wygląda to (w tym wyniki dla różnych metod i wartości - czas działania 7 minut): gist.github.com/ecki/ 399136f4fd59c1d110c1 (spoiler: „” + n wygrane).
eckes

5
Dzięki kolego, ale moja odpowiedź była 5 lat temu! JMH został wydany dopiero w 2013 roku: P
Kingo

9

Ze źródeł Java:

/**
 * Returns the string representation of the {@code int} argument.
 * <p>
 * The representation is exactly the one returned by the
 * {@code Integer.toString} method of one argument.
 *
 * @param   i   an {@code int}.
 * @return  a string representation of the {@code int} argument.
 * @see     java.lang.Integer#toString(int, int)
 */
public static String valueOf(int i) {
    return Integer.toString(i);
}

Dają więc dokładnie ten sam wynik i faktycznie jeden wywołuje drugi. String.valueOf jest bardziej elastyczny, jeśli możesz później zmienić typ.


8

Jeśli spojrzysz na kod źródłowy Stringklasy, w rzeczywistości wywołuje on, Integer.toString()gdy dzwonisz valueOf().

To powiedziawszy, Integer.toString()może być odrobinę szybsze, jeśli wywołania metod nie są zoptymalizowane w czasie kompilacji (co prawdopodobnie jest).


Tak, a „” + n jest jeszcze szybsze. Zobacz gist.github.com/ecki/399136f4fd59c1d110c1
eckes


2

Odpowiadając na pytanie PO, wystarczy, że otrzyma drugie wezwanie, aby uzyskać pomoc, i sprowadza się do wyboru stylu i to wszystko. Myślę, że jest tu wiele błędnych informacji, a najlepszą rzeczą, jaką może zrobić programista Java, jest przyjrzenie się implementacji dla każdej metody, jest to jedno lub dwa kliknięcia w dowolnym IDE. Wyraźnie zobaczysz, że String.valueOf(int)po prostu Integer.toString(int)cię wzywa .

Dlatego różnica jest absolutnie zerowa, ponieważ obaj tworzą bufor znaków, przechodzą przez cyfry w numerze, a następnie kopiują go do nowego ciągu i zwracają (dlatego każdy z nich tworzy jeden obiekt String). Jedyną różnicą jest jedno dodatkowe wywołanie, które i tak kompilator eliminuje do pojedynczego wywołania.

Więc nie ma znaczenia, który dzwonisz, może poza spójnością kodu. Jeśli chodzi o komentarze o wartościach zerowych, to zajmuje prymityw, dlatego nie może być zerowe! Jeśli nie zainicjujesz przekazywanego int, otrzymasz błąd kompilacji. Nie ma więc różnicy w sposobie obsługi wartości null, ponieważ w tym przypadku nie istnieją.


Czy mógłbyś podzielić swój tekst na kilka bloków. Bardzo trudno to czytać.
Magnilex,

W tym PO jest dużo błędnych informacji. Twój post jest dla mnie najlepszą odpowiedzią! Dziękuję
aksappy

1

Nie powinieneś się martwić o to dodatkowe połączenie, które kosztuje Cię problemy z wydajnością. Jeśli są jakieś koszty, będą one minimalne i powinny być nieistotne w szerszej perspektywie.

Być może powodem, dla którego istnieją oba, jest zapewnienie czytelności. W kontekście konwertowania wielu typów na Stringróżne wywołania String.valueOf(SomeType)mogą być bardziej czytelne niż różne SomeType.toStringwywołania.


1
W rzeczywistości takie jednowierszowe połączenia są wprowadzane dość szybko.
Tassos Bassoukos

Nawet w pętli wywołującej 1 000 000 razy String.valueof () ??
Manuel Selva

@Manuel: profilowałeś to? Czy zidentyfikowałeś, że tutaj leży twój problem z wydajnością? Czy na pewno nie optymalizujesz przedwcześnie? @ Tassos: tak, to również jest bardzo prawdopodobne, ale tak czy inaczej nie martwiłbym się tym, chyba że profilowanie mówi, że jest problem z tym konkretnym połączeniem.
smary wielogenowe

Właściwie, Manuel, spodziewałbym się, że pętla przechodząca 1000000 razy będzie częściej wstawiana niż tylko raz lub dwa razy. Mimo to będzie to niewielka część czasu, bez względu na to, ile razy się zapętli.
corsiKa

Nie, ale jestem pewien, że w mojej aplikacji nie ma szyjki butelki. Pytam tylko o to, ponieważ nie widzę tutaj żadnych problemów z czytelnością i dlatego myślę, że muszę użyć bardziej optymalnego kodu, nawet jeśli zysk wynosi 0. Nie zgadzasz się?
Manuel Selva

1

moje otwarcie jest valueof () zawsze nazywane tostring () dla reprezentacji, więc dla rpresentaion typu primtive valueof jest uogólniona. a java domyślnie nie obsługuje typu danych, ale definiuje swoją pracę z objaect i class, wszystko zostało zrobione w cllas i zrobione obiekt .here Integer.toString (int i) tworzy ograniczenie tej konwersji tylko dla liczby całkowitej.


1

Nie ma różnic między Integer.toString (5) i String.valueOf (5);

ponieważ String.valueOf zwraca:

public static String valueOf(int i) {
    return Integer.toString(i);
}
public static String valueOf(float f) {
    return Float.toString(f);
}

itp..


0

Używając metody String.valueOf () nie musisz martwić się o dane (czy są to int, long, char, char [], boolean, Object), możesz po prostu wywołać:

  • statyczna wartość ciągu ()

przy użyciu jedynej składni String.valueOf () wszystko, co przekażesz jako parametr, zostanie przekonwertowane na String i zwrócone.

W przeciwnym razie, jeśli używasz Integer.toString (), Float.toString () itp. (Np. SomeType.toString ()), będziesz musiał sprawdzić typ danych parametru, który chcesz przekonwertować na łańcuch. Dlatego lepiej jest użyć String.valueOf () do takich konwersji.

Jeśli masz tablicę klas obiektów, która zawiera różne wartości, takie jak Integer, Char, Float itp., To za pomocą metody String.valueOf () możesz łatwo przekonwertować elementy takiej tablicy do postaci String. Wręcz przeciwnie, jeśli chcesz użyć SomeType.toString (), to najpierw będziesz musiał wiedzieć o ich klasach typów danych (być może za pomocą operatora „instanceOf”), a dopiero potem możesz przejść do rzutowania typu.

Wywoływana metoda String.valueOf () odpowiada przekazanemu parametrowi (czy to Integer, Char, Float itp.), A przez przeciążenie metody wywołuje metodę „valueOf ()”, której parametr jest dopasowywany, a następnie wewnątrz tej metody jest bezpośrednie wywołanie odpowiedniej metody „toString ()”.

Możemy więc zobaczyć, jak usuwa się obciążenie związane ze sprawdzaniem typu danych, a następnie wywoływaniem odpowiedniej metody "toString ()". Wystarczy tylko wywołać metodę String.valueOf (), nie dbając o to, co chcemy przekonwertować na String.

Wniosek: Metoda String.valueOf () ma swoje znaczenie tylko kosztem jeszcze jednego wywołania.


-3

toString ()

  1. jest obecny w klasie Object, zwykle nadpisywany w klasie pochodnej
  2. typecast do odpowiedniej klasy jest konieczne do wywołania metody toString ().

wartość()

  1. Przeciążona metoda statyczna obecna w klasie String.
  2. obsługuje zarówno typy pierwotne, jak i typy obiektów.

    Integer a = null;
    System.out.println(Integer.toString()) ; NUll pointer exception
    System.out.println(String.valueOf() ; give NULL as value

sprawdź ten link jest bardzo dobry. http://code4reference.com/2013/06/which-one-is-better-valueof-or-tostring/

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.