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


176

Mi chiedo perché String.valueOf(int i)esiste il metodo ? Sto usando questo metodo per convertire intin Stringe appena scoperto il Integer.toString(int i)metodo.

Dopo aver visto l'implementazione di questi metodi, ho visto che il primo chiama il secondo. Di conseguenza, tutte le mie chiamate String.valueOf(int i)prevedono una chiamata in più rispetto alla chiamata direttaInteger.toString(int i)


Risposte:


46

Solo due modi diversi di fare la stessa cosa. Potrebbe essere una ragione storica (non ricordo se l'uno è venuto prima dell'altro).


22
Sì, ma se qualcosa fa lo stesso, non significa che siano la stessa cosa.
Damian Leszczyński - Vash,

3
String.valueOf (int) chiama semplicemente Integer.toString (i) direttamente. Quindi è meglio chiamare Integer.toString (int).
djchapm,

171

Nel tipo String abbiamo diversi metodi 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) 

Come possiamo vedere, questi metodi sono in grado di risolvere tutti i tipi di numeri

ogni implementazione di un metodo specifico come quello che hai presentato: quindi per gli interi abbiamo

Integer.toString(int i)

per doppio

Double.toString(double d)

e così via

A mio avviso, questa non è una cosa storica, ma è più utile per uno sviluppatore utilizzare il metodo valueOfdalla classe String piuttosto che dal tipo corretto, in quanto comporta meno modifiche da apportare.

Esempio 1:

public String doStuff(int num) {

  // Do something with num...

  return String.valueOf(num);

 }

Sample2:

public String doStuff(int num) {

 // Do something with num...

 return Integer.toString(num);

 }

Come vediamo nel campione 2, dobbiamo fare due modifiche, al contrario del campione uno.

In conclusione, l'uso del valueOfmetodo dalla classe String è più flessibile ed è per questo che è disponibile lì.


18
E non dimenticare Integer.toString(int i, int radix)che si convertirà in stringhe di basi diverse da 10.
Stephen P

@Vash Potresti anche spiegare come usare la stringa vuota per convertire int in String rispetto a String.valueOf? es.) "" + int i = "i"? Qual è la migliore?
Kanagavelu Sugumar,

1
Per formattare int come stringa non dovresti usare "" + i. Non esiste un grande overhead ma generalmente perché questo non è elegante. Invece di usare String.valueOf(int), puoi usare String.format("%d",i);per leggere di più, visita questo sito Web docs.oracle.com/javase/6/docs/api/java/util/Formatter.html
Damian Leszczyński - Vash

Vorrei che l'autoboxing fosse più intelligente e abbia appena aggiunto la conversione in compilation o qualcosa del genere.
Rob Grant,

1
@RobertGrant Qui l'autoboxing non è il caso. Ma per rispondere alle tue preoccupazioni, è intelligente come puoi farlo int i = new Integer("1");e viceversa.
Damian Leszczyński - Vash,

52

Una grande differenza è che se invochi toString()in un oggetto null otterrai un NullPointerExceptionconsiderando, mentre usando String.valueOf()potresti non controllare null.


46
La domanda riguarda Integer.toString(int i)un staticmetodo. Non ci sono nulloggetti possibili.
Petr Janeček,

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

10
@Manis Kumar: il tuo esempio non attiverà il String.valueOf(int i)metodo ma String.valueOf(Object obj). Comunque, la domanda riguarda i intvalori primitivi , dove non c'è possibilità null.
hleinone,

1
@manish_s dall'esempio era abbastanza chiaro che nessuno parla del tipo di oggetto Numero intero. Stiamo solo parlando di primitivi.
Daniel Ochoa,

2
@manish_s: L'OP non ha detto Integer.toString()ma Integer.toString(int i). Questo è un metodo statico ( docs.oracle.com/javase/7/docs/api/java/lang/… ).
LarsH,

13

La classe String fornisce metodi valueOf per tutti i tipi primitivi e il tipo di oggetto, quindi suppongo che siano metodi di praticità a cui è possibile accedere tutti tramite una classe.

NB Risultati della profilazione

IntToString medio = 5368 ms, valore medio stringa stringa = 5689 ms (per 100.000.000 di operazioni)

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
La profilazione dovrebbe davvero avere un periodo di "riscaldamento", altrimenti i risultati possono essere distorti dal JIT che armeggia con le cose. Detto questo, una differenza di 300 ms su 10 ^ 8 operazioni è così piccola da essere completamente trascurabile.
Cameron Skinner,

1
@Kingo Non credo che il tuo test case sia corretto. Perché stai assegnando il valore String jma non lo usi mai. Il compilatore sottostante potrebbe averlo ottimizzato. È meglio passare l'oggetto j in un metodo diverso ed eseguire alcune operazioni fittizie.
Rakesh,

1
Non dovresti davvero scrivere micro benchmark fatti in casa in questo modo. Se usi JMH . Si occuperà di riscaldamento, misurazione del tempo, più tentativi indipendenti (forcelle Java!) E rende il codice piccolo, sembra (incl. Risultati per metodi e valori diversi - tempo di esecuzione 7 minuti): gist.github.com/ecki/ 399136f4fd59c1d110c1 (spoiler: "" + n vinto).
diamine

5
Grazie amico, ma la mia risposta è stata 5 anni fa! JMH è stato rilasciato solo nel 2013: P
Kingo l'

9

Dalle fonti 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);
}

Quindi danno esattamente lo stesso risultato e uno infatti chiama l'altro. String.valueOf è più flessibile se è possibile modificare il tipo in un secondo momento.


8

Se guardi il codice sorgente per la Stringclasse, in realtà chiama Integer.toString()quando chiami valueOf().

Detto questo, Integer.toString()potrebbe essere un po 'più veloce se le chiamate al metodo non sono ottimizzate in fase di compilazione (cosa che probabilmente lo sono).


Sì e "" + n è ancora più veloce. Vedi gist.github.com/ecki/399136f4fd59c1d110c1
eckes

3

L'implementazione di String.valueOf()quello che vedi è il modo più semplice per soddisfare il contratto specificato nell'API: "La rappresentazione è esattamente quella restituita dal Integer.toString()metodo di un argomento".


2

Per rispondere alla domanda dei PO, è semplicemente un helper wrapper avere l'altra chiamata, e arriva alla scelta dello stile e basta. Penso che ci sia molta disinformazione qui e la cosa migliore che uno sviluppatore Java possa fare è guardare l'implementazione per ciascun metodo, è uno o due clic di distanza in qualsiasi IDE. Vedrai chiaramente che ti String.valueOf(int)sta semplicemente chiamando Integer.toString(int).

Pertanto, non vi è assolutamente alcuna differenza, in quanto entrambi creano un buffer di caratteri, camminano attraverso le cifre del numero, quindi lo copiano in una nuova stringa e lo restituiscono (quindi ognuno di essi crea un oggetto String). L'unica differenza è una chiamata aggiuntiva, che il compilatore elimina comunque in una singola chiamata.

Quindi non importa quale si chiama, a parte forse la coerenza del codice. Per quanto riguarda i commenti sui null, ci vuole una primitiva, quindi non può essere null! Riceverai un errore di compilazione se non inizializzi l'int che viene passato. Quindi non vi è alcuna differenza nel modo in cui gestisce i null in quanto inesistenti in questo caso.


Potresti per favore separare il tuo testo in alcuni blocchi. È molto difficile da leggere.
Magnilex,

Ci sono molte cose male informate in questo PO. Il tuo post è la risposta migliore per me! Grazie
aksappy,

1

Non dovresti preoccuparti di questa chiamata extra che ti costa problemi di efficienza. Se ci sono costi, sarà minimo e dovrebbe essere trascurabile nel quadro più ampio delle cose.

Forse il motivo per cui entrambi esistono è offrire leggibilità. Nel contesto in cui molti tipi vengono convertiti String, allora varie chiamate a String.valueOf(SomeType)potrebbero essere più leggibili di varie SomeType.toStringchiamate.


1
In realtà, tali chiamate a una linea vengono inserite abbastanza rapidamente.
Tassos Bassoukos,

Anche in un ciclo che chiama 1 000 000 di tempo String.valueof () ??
Manuel Selva,

@Manuel: l'hai profilato? Hai identificato che qui sta il tuo problema di prestazioni? Sei sicuro di non ottimizzare prematuramente? @Tassos: sì, è anche molto probabile, ma in entrambi i casi non mi preoccuperei a meno che la profilazione non dica che c'è un problema con questa chiamata particolare.
poligenilubrificanti,

A dire il vero, Manuel, mi aspetto che un loop che vada 1000000 volte si allinei più spesso di una o due volte. Anche così, sarà una piccola parte del tempo, non importa quante volte il ciclo.
corsiKa

No, ma sono sicuro che non ci sia collo di bottiglia qui nella mia app. Lo sto solo chiedendo perché non riesco a vedere alcuna preoccupazione di leggibilità qui e quindi penso di dover usare il codice più ottimale anche se il guadagno è 0. Non sei d'accordo?
Manuel Selva,

1

la mia apertura è valueof () sempre chiamato tostring () per la rappresentazione e quindi per la rappresentazione di tipo primitivo il valore di è generalizzato. object .here Integer.toString (int i) crea un limite per quella conversione solo per intero.


1

Non ci sono differenze tra Integer.toString (5) e String.valueOf (5);

perché String.valueOf restituisce:

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

eccetera..


0

Usando il metodo String.valueOf () non devi preoccuparti dei dati (sia esso int, long, char, char [], boolean, Object), puoi semplicemente chiamare:

  • String String valueOf ()

usando l'unica sintassi String.valueOf (), qualunque cosa passi come parametro viene convertita in String e restituita.

Altrimenti, se si utilizza Integer.toString (), Float.toString () ecc. (Ovvero SomeType.toString ()), sarà necessario verificare il tipo di dati del parametro che si desidera convertire in stringa. Quindi, è meglio usare String.valueOf () per tali conversioni.

Se si dispone di un array di classi di oggetti che contiene valori diversi come Integer, Char, Float ecc., Quindi utilizzando il metodo String.valueOf () è possibile convertire facilmente gli elementi di tale array in formato String. Al contrario, se si desidera utilizzare SomeType.toString (), all'inizio sarà necessario conoscere le loro classi di tipi di dati (magari utilizzando l'operatore "instanceOf") e solo allora è possibile procedere per un typecast.

Il metodo String.valueOf () quando chiamato corrisponde al parametro che viene passato (sia Integer, Char, Float ecc.) E usando il metodo overloading chiama quel metodo "valueOf ()" il cui parametro viene abbinato, e quindi all'interno di quel metodo il loro è una chiamata diretta al corrispondente metodo "toString ()".

Quindi, possiamo vedere come viene rimosso l'overhead del controllo del tipo di dati e quindi della chiamata del metodo "toString ()" corrispondente. Solo dobbiamo chiamare il metodo String.valueOf (), senza preoccuparci di ciò che vogliamo convertire in String.

Conclusione: il metodo String.valueOf () ha la sua importanza solo al costo di un'altra chiamata.


-3

accordare()

  1. è presente nella classe Object, generalmente sovrascritto nella classe derivata
  2. è necessario digitare in classe appropriata per chiamare il metodo toString ().

valore di()

  1. Metodo statico sovraccarico presente nella classe String.
  2. gestisce tipi primitivi e tipi di oggetti.

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

controlla questo link è molto buono. http://code4reference.com/2013/06/which-one-is-better-valueof-or-tostring/

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.