Pregunta

¿Cómo multiplico 10 por un? Integer objeto y recuperar el Integer ¿objeto?

Estoy buscando la forma más sencilla de hacer esto.

Probablemente lo haría de esta manera:Obtener entrada desde Integer objeto, multiplíquelo con el otro int y cree otro objeto Integer con este valor int.

El código será algo así como...

integerObj = new Integer(integerObj.intValue() * 10);

Pero vi un código en el que el autor lo hace de esta manera:Consigue el String desde el Integer objeto, concatenar "0" al final y luego obtener Integer objeto de vuelta usando Integer.parseInt

El código es algo como esto:

String s = integerObj + "0";
integerObj = Integer.parseInt(s);

¿Hay algún mérito en hacerlo de cualquier manera?

¿Y cuál sería la forma más eficiente/más sencilla en general y en este caso?

¿Fue útil?

Solución

Con Java 5 autoboxing, simplemente puedes hacer:

Integer a = new Integer(2); // or even just Integer a = 2;
a *= 10;
System.out.println(a);

Otros consejos

El enfoque con cuerdas es divertido, pero casi con certeza es una mala forma de hacerlo.

Obtener el valor int de un número entero y crear uno nuevo será muy rápido, mientras que llamar a parseInt sería bastante costoso.

En general, estoy de acuerdo con su enfoque original (que, como otros han señalado, se puede hacer sin tanto desorden si tiene autoboxing como se introdujo en Java 5).

El problema con la segunda forma es la forma en que se manejan las cadenas en Java:

  • "0" se convierte en un objeto String constante en el momento de la compilación.
  • Cada vez que se llama a este código, s se construye como un nuevo objeto String, y javac convierte ese código a String s = new StringBuilder().append(integerObj.toString()).append("0").toString() (StringBuffer para versiones anteriores).Incluso si usas el mismo integerObj, es decir.,

    String s1 = integerObj + "0"; String s2 = integerObj + "0";

    (s1 == s2) sería false, mientras s1.equals(s2) sería true.

  • Integer.parseInt llamadas internas new Integer() de todos modos, porque Integer es inmutable.

Por cierto, el autoboxing/unboxing es internamente el mismo que el primer método.

Manténgase alejado del segundo enfoque, la mejor opción sería el autoboxing si está usando Java 1.5, cualquier cosa anterior a su primer ejemplo sería lo mejor.

La solución que utiliza el método String no es tan buena por varias razones.Algunas son razones estéticas, otras son prácticas.

Desde un punto de vista práctico, la versión String crea más objetos que la forma más normal (como ha expresado en su primer ejemplo).

En una nota estética, creo que la segunda versión oscurece la intención del código y eso es casi tan importante como lograr que produzca el resultado deseado.

La respuesta anterior del kit de herramientas es correcta y la mejor manera, pero no brinda una explicación completa de lo que está sucediendo.Suponiendo Java 5 o posterior:

Integer a = new Integer(2); // or even just Integer a = 2;
a *= 10;
System.out.println(a); // will output 20

Lo que necesitas saber es que esto es exactamente lo mismo que hacer:

Integer a = new Integer(2); // or even just Integer a = 2;
a = a.intValue() * 10;
System.out.println(a.intValue()); // will output 20

Al realizar la operación (en este caso *=) en el objeto 'a', no estás cambiando el valor int dentro del objeto 'a', sino que en realidad estás asignando un nuevo objeto a 'a'.Esto se debe a que 'a' se desempaqueta automáticamente para realizar la multiplicación, y luego el resultado de la multiplicación se desempaqueta automáticamente y se asigna a 'a'.

El número entero es un objeto inmutable.(Todas las clases contenedoras son inmutables).

Tomemos, por ejemplo, este fragmento de código:

static void test() {
    Integer i = new Integer(10);
    System.out.println("StartingMemory: " + System.identityHashCode(i));
    changeInteger(i);
    System.out.println("Step1: " + i);
    changeInteger(++i);
    System.out.println("Step2: " + i.intValue());
    System.out.println("MiddleMemory: " + System.identityHashCode(i));
}

static void changeInteger(Integer i) {
    System.out.println("ChangeStartMemory: " + System.identityHashCode(i));
    System.out.println("ChangeStartValue: " + i);
    i++;
    System.out.println("ChangeEnd: " + i);
    System.out.println("ChangeEndMemory: " + System.identityHashCode(i));
}

La salida será:

StartingMemory: 1373539035
ChangeStartMemory: 1373539035
ChangeStartValue: 10
ChangeEnd: 11
ChangeEndMemory: 190331520
Step1: 10
ChangeStartMemory: 190331520
ChangeStartValue: 11
ChangeEnd: 12
ChangeEndMemory: 1298706257
Step2: 11
MiddleMemory: 190331520

Puede ver que la dirección de memoria para 'i' está cambiando (sus direcciones de memoria serán diferentes).

Ahora hagamos una pequeña prueba con reflexión, agreguemos esto al final del método test():

System.out.println("MiddleMemory: " + System.identityHashCode(i));
try {
    final Field f = i.getClass().getDeclaredField("value");
    f.setAccessible(true);
    f.setInt(i, 15);
    System.out.println("Step3: " + i.intValue());
    System.out.println("EndingMemory: " + System.identityHashCode(i));
} catch (final Exception e) {
    e.printStackTrace();
}

La salida adicional será:

MiddleMemory: 190331520
Step2: 15
MiddleMemory: 190331520

Puede ver que la dirección de memoria para 'i' no cambió, aunque cambiamos su valor mediante la reflexión.
(¡¡NO USE LA REFLEXIÓN DE ESTA MANERA EN LA VIDA REAL!!)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top