¿Cómo multiplicar 10 por un objeto "entero" en Java?
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?
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, yjavac
convierte ese código aString s = new StringBuilder().append(integerObj.toString()).append("0").toString()
(StringBuffer para versiones anteriores).Incluso si usas el mismointegerObj
, es decir.,String s1 = integerObj + "0"; String s2 = integerObj + "0";
(s1 == s2)
seríafalse
, mientrass1.equals(s2)
seríatrue
.Integer.parseInt
llamadas internasnew Integer()
de todos modos, porqueInteger
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!!)