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

175

Me pregunto por qué String.valueOf(int i)existe el método . Estoy utilizando este método para convertir inten Stringy acabo de descubrir el Integer.toString(int i)método.

Después de mirar la implementación de estos métodos, vi que el primero llama al segundo. Como consecuencia, todas mis llamadas String.valueOf(int i)implican una llamada más que llamar directamenteInteger.toString(int i)

Manuel Selva
fuente
3
Solo para fines de referencia: stackoverflow.com/questions/3335685/integer-tostring
Bobby

Respuestas:

46

Solo dos formas diferentes de hacer lo mismo. Puede ser una razón histórica (no recuerdo si uno vino antes que el otro).

mipadi
fuente
22
Sí, pero si algo está haciendo lo mismo, no significa que sea lo mismo.
Damian Leszczyński - Vash
3
String.valueOf (int) solo llama a Integer.toString (i) directamente. Lo mejor es llamar a Integer.toString (int).
djchapm
171

En el tipo de cadena tenemos varios métodos 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) 

Como podemos ver, esos métodos son capaces de resolver todo tipo de números

cada implementación de un método específico como el que has presentado: Entonces, para enteros

Integer.toString(int i)

para doble

Double.toString(double d)

y así

En mi opinión, esto no es algo histórico, pero es más útil para un desarrollador usar el método valueOfde la clase String que del tipo adecuado, ya que nos lleva a realizar menos cambios.

Muestra 1:

public String doStuff(int num) {

  // Do something with num...

  return String.valueOf(num);

 }

Muestra2:

public String doStuff(int num) {

 // Do something with num...

 return Integer.toString(num);

 }

Como vemos en la muestra 2, tenemos que hacer dos cambios, a diferencia de la muestra uno.

En mi conclusión, usar el valueOfmétodo de la clase String es más flexible y es por eso que está disponible allí.

Damian Leszczyński - Vash
fuente
18
Y no olvide Integer.toString(int i, int radix)que se convertirá en cadenas de bases que no sean 10.
Stephen P
@Vash ¿Podría explicar también cómo usar una cadena vacía para convertir int en String en comparación con String.valueOf? por ejemplo) "" + int i = "i"? Cuál es el mejor ?
Kanagavelu Sugumar
1
Para formatear int como cadena no debe usar "" + i. No existe gran sobrecarga, pero generalmente porque esto no es elegante. En lugar de usar String.valueOf(int), puede usar String.format("%d",i);para leer más, visite este sitio web docs.oracle.com/javase/6/docs/api/java/util/Formatter.html
Damian Leszczyński - Vash
Desearía que el autoboxing fuera más inteligente y solo agregara la conversión en la compilación o algo así.
Rob Grant
1
@RobertGrant El autoboxing no es el caso aquí. Pero para responder a sus inquietudes, es inteligente, ya que puede hacer esto int i = new Integer("1");y viceversa.
Damian Leszczyński - Vash
52

Una gran diferencia es que si invoca toString()en un objeto nulo obtendrá un NullPointerExceptionmientras que, al usarlo, String.valueOf()es posible que no compruebe si es nulo.

Una costa
fuente
46
La pregunta es sobre Integer.toString(int i)un staticmétodo. No hay nullobjetos posibles.
Petr Janeček
14
Integer i = null; i.toString(); // Null pointer exception!! String.valueOf(i); // No exception
manish_s
10
@Manis Kumar: Su ejemplo no activará el String.valueOf(int i)método pero String.valueOf(Object obj). De todos modos, la pregunta es sobre intvalores primitivos , donde no hay posibilidad de null.
hleinone 01 de
1
@manish_s fue bastante claro en el ejemplo que nadie está hablando sobre el tipo de objeto Integer. Solo estamos hablando de primitivas.
Daniel Ochoa
2
@manish_s: El OP no dijo Integer.toString()pero Integer.toString(int i). Ese es un método estático ( docs.oracle.com/javase/7/docs/api/java/lang/… ).
LarsH
13

La clase String proporciona métodos valueOf para todos los tipos primitivos y tipo Object, por lo que supongo que son métodos convenientes a los que se puede acceder a través de una clase.

NB Resultados de perfiles

Promedio intToString = 5368 ms, Promedio stringValueOf = 5689 ms (para 100,000,000 operaciones)

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));
    }
}
Kingo
fuente
77
Su perfil realmente debería tener un período de "calentamiento", de lo contrario los resultados pueden ser sesgados por el JIT jugando con las cosas. Dicho esto, una diferencia de 300 ms sobre 10 ^ 8 operaciones es tan pequeña que puede ser completamente insignificante.
Cameron Skinner
1
@Kingo No creo que su caso de prueba sea correcto. Porque está asignando el valor String jpero nunca lo usa. El compilador subyacente puede haber optimizado esto. Es mejor pasar j objeto en un método diferente y hacer alguna operación ficticia.
Rakesh
1
Realmente no deberías escribir micro puntos de referencia de cosecha propia de esta manera. Si usas JMH . Se ocupará del calentamiento, la medición del tiempo, múltiples intentos independientes (¡bifurca Java!) Y hace que el código sea pequeño, como se ve (incluidos los resultados para diferentes métodos y valores - tiempo de ejecución 7 minutos): gist.github.com/ecki/ 399136f4fd59c1d110c1 (spoiler: "" + n ganado).
Eckes
55
Gracias amigo, ¡pero mi respuesta fue hace 5 años! JMH solo se lanzó en 2013: P
Kingo
9

De las fuentes 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);
}

Entonces dan exactamente el mismo resultado y uno de hecho llama al otro. String.valueOf es más flexible si puede cambiar el tipo más adelante.

Davio
fuente
8

Si observa el código fuente de la Stringclase, en realidad llama Integer.toString()cuando llama valueOf().

Dicho esto, Integer.toString()podría ser un poco más rápido si las llamadas al método no están optimizadas en el momento de la compilación (que probablemente sí lo estén).

tskuzzy
fuente
Sí y "" + n es aún más rápido. Ver gist.github.com/ecki/399136f4fd59c1d110c1
eckes
3

La implementación de lo String.valueOf()que ve es la forma más sencilla de cumplir con el contrato especificado en la API: "La representación es exactamente la que devuelve el Integer.toString()método de un argumento".

trashgod
fuente
2

Para responder a la pregunta de los OP, es simplemente un contenedor auxiliar para tener la otra llamada, y se reduce a la elección de estilo y eso es todo. Creo que hay mucha información errónea aquí y lo mejor que puede hacer un desarrollador de Java es mirar la implementación de cada método, está a uno o dos clics de distancia en cualquier IDE. Verá claramente que String.valueOf(int)simplemente está llamandoInteger.toString(int) te .

Por lo tanto, no hay absolutamente ninguna diferencia, ya que ambos crean un búfer de caracteres, recorren los dígitos del número, luego lo copian en una nueva Cadena y lo devuelven (por lo tanto, cada uno está creando un objeto Cadena). La única diferencia es una llamada adicional, que el compilador elimina a una sola llamada de todos modos.

Por lo tanto, no importa a qué llame, aparte de la coherencia del código. En cuanto a los comentarios sobre nulos, se necesita una primitiva, por lo tanto, no puede ser nulo. Obtendrá un error en tiempo de compilación si no inicializa el int que se pasa. Por lo tanto, no hay diferencia en cómo maneja los nulos, ya que son inexistentes en este caso.

Steve J
fuente
¿Podría por favor separar su texto en algunos bloques? Es muy dificil de leer.
Magnilex
Hay muchas cosas mal informadas en este OP. ¡Tu publicación es la mejor respuesta para mí! Gracias
aksappy
1

No debe preocuparse por esta llamada adicional que le costará problemas de eficiencia. Si hay algún costo, será mínimo y debería ser insignificante en el panorama general de las cosas.

Quizás la razón por la cual ambos existen es para ofrecer legibilidad. En el contexto de muchos tipos que se convierten String, entonces varias llamadas a String.valueOf(SomeType)pueden ser más legibles que varias SomeType.toStringllamadas.

poligenelubricantes
fuente
1
En realidad, esas llamadas de una línea se insertan con bastante rapidez.
Tassos Bassoukos
Incluso en un bucle llamando a 1 000 000 de tiempo String.valueof () ??
Manuel Selva
@Manuel: ¿lo perfilaste? ¿Ha identificado que aquí radica su problema de rendimiento? ¿Estás seguro de que no estás optimizando prematuramente? @Tassos: sí, eso también es muy probable, pero de cualquier manera no me preocuparía a menos que el perfil indique que hay un problema con esta llamada en particular.
polygenelubricants
En realidad, Manuel, esperaría que un bucle que se ejecuta 1000000 veces se inserte con más frecuencia que una o dos veces. Aun así, será una pequeña parte del tiempo, sin importar cuántas veces se repita.
corsiKa
No, pero estoy seguro de que no hay cuello de botella aquí en mi aplicación. Solo pregunto esto porque no puedo ver ningún problema de legibilidad aquí y, por lo tanto, creo que tengo que usar el código más óptimo incluso si la ganancia es 0. ¿No está de acuerdo?
Manuel Selva
1

mi apertura es valueof () siempre llamada tostring () para la representación y, por lo tanto, para la representación del tipo primitivo valueof se generaliza. y Java por defecto no admite el tipo de datos, pero define su trabajo con objaect y la clase se hizo todo en cllas y se hizo object .here Integer.toString (int i) crea un límite de conversión para solo enteros.

anuragsingh
fuente
1

No hay diferencias entre Integer.toString (5) y String.valueOf (5);

porque String.valueOf devuelve:

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

etc.

Ahamadullah Saikat
fuente
0

Usando el método String.valueOf () no tiene que preocuparse por los datos (ya sea int, long, char, char [], boolean, Object), simplemente puede llamar:

  • valor de cadena estática Of ()

utilizando la única sintaxis String.valueOf () puede convertir lo que pase como parámetro en String y devolverlo.

De lo contrario, si usa Integer.toString (), Float.toString () etc. (es decir, SomeType.toString ()), deberá verificar el tipo de datos del parámetro que desea convertir en cadena. Por lo tanto, es mejor usar String.valueOf () para tales conversiones.

Si tiene una matriz de clase de objeto que contiene diferentes valores como Integer, Char, Float, etc., utilizando el método String.valueOf () puede convertir fácilmente los elementos de dicha matriz en forma de cadena. Por el contrario, si desea utilizar SomeType.toString (), al principio deberá conocer sus clases de tipo de datos (tal vez mediante el uso del operador "instanceOf") y luego solo podrá proceder a una conversión tipográfica.

El método String.valueOf () cuando se llama coincide con el parámetro que se pasa (ya sea Integer, Char, Float, etc.) y al usar la sobrecarga de métodos llama a ese método "valueOf ()" cuyo parámetro coincide, y luego dentro de ese método es una llamada directa al método "toString ()" correspondiente.

Por lo tanto, podemos ver cómo se elimina la sobrecarga de verificar el tipo de datos y luego llamar al método "toString ()" correspondiente. Solo necesitamos llamar al método String.valueOf (), sin preocuparnos por lo que queremos convertir a String.

Conclusión: el método String.valueOf () tiene su importancia al costo de una llamada más.

Amit Bhandari
fuente
-3

Encadenar()

  1. está presente en la clase Object, generalmente anulada en la clase derivada
  2. La conversión de texto a la clase apropiada es necesaria para llamar al método toString ().

valor de()

  1. Método estático sobrecargado presente en la clase String.
  2. maneja tipos primitivos así como tipos de objetos.

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

mira este enlace es muy bueno http://code4reference.com/2013/06/which-one-is-better-valueof-or-tostring/

shruti
fuente