2012-10-05 33 views
5

El escenario es que necesito acceder a un valor al menos dos veces. Es decir. Estoy usando el registrador para hacer un seguimiento de lo que está sucediendo en la aplicación. Quiero registrar el nombre del objeto, esa función está trabajando, y luego hacer algo con el mismo nombre (es decir, verificar si contiene alguna cadena o ponerla en una matriz).¿Usa variables para almacenar valores u obtener valores directamente de los objetos?

Memorizar el nombre de la variable:

foo(Bar bar){ 
    String name = bar.getName(); 
    logger.info("I am working with "+name); 
    this.doSomethingWith(name); 
} 

O llamando getName() dos veces:

foo(Bar bar){ 
    logger.info("I am working with "+bar.getName()); 
    this.doSomethingWith(bar.getName()); 
} 

entiendo, que en el primer escenario, que va a crear una nueva cadena, asignar un valor a él y luego recuperar este valor dos veces. De esta forma estoy usando más recursos de memoria, ¿correcto?

En el segundo caso, estoy accediendo a la barra de objetos dos veces y luego accediendo a su nombre dos veces. Supongo que este no es un enfoque SECO. Pero, por otro lado, no me repito en la memoria, ¿correcto?

¿Qué enfoque es mejor?

+0

En el primer método, _no estás_ creando un nuevo String. Entonces ambos métodos deberían terminar con el mismo consumo de memoria. – Fildor

+0

Puede valer la pena verificar el código de bytes generado con un descompilador para ver si su problema es realmente un problema; 'javac' podría reconocer este caso de uso y optimizarlo de una forma u otra sin importar en qué dirección lo escriba en Java. – akaIDIOT

Respuesta

1

Personalmente, prefiero el segundo enfoque. De hecho, generalmente creo variables temporales únicamente cuando es necesario.

Martin Fowler (http://en.wikipedia.org/wiki/Martin_Fowler) también sigue esta guía. Se relaciona en su libro que he leído:

http://www.amazon.fr/Refactoring-Improving-Design-Existing-Code/dp/0201485672

Un extracto libre de su libro en relación con este tema es aquí:

http://sourcemaking.com/refactoring/replace-temp-with-query

Algunas personas podrían argumentar la eliminación de variables temporales podrían conducir a un problema de rendimiento.

Como Martin Fowler dice:

Usted puede estar preocupado por el rendimiento en este caso. Al igual que con otros problemas de rendimiento , déjalo deslizar por el momento. Nueve veces fuera de diez, no importará. Cuando sí importa, reparará el problema durante la optimización.Con su código mejor factorizado, a menudo encontrará optimizaciones más potentes, que se habría perdido sin refactorización. Si empeora, es muy fácil volver a poner la temperatura .

Pero de todos modos, es una cuestión de gusto. Algunas personas encuentran más legible el primer acercamiento, otras el segundo. Realmente prefiero el segundo porque odio las variables temporales al agregar líneas sin valores reales :)

+0

Este enfoque Martin Fowler ... es INCREÍBLE! – user1581900

+0

@ user1581900 Deberías leer su libro, me encantó :) Ver también Robert C Martin para el libro "Código limpio" :) – Mik378

1

Su Bar debe ser de clase inmutable (para la mayoría de los casos). Para la clase inmutable estos enfoques son los mismos, por lo que elige lo que quiera.

Cualquier problema real ocurrirá solo si Bar es mutable, entonces el valor de bar.name puede cambiar entre 2 lecturas. Pero este caso representará el uso de Bar como objeto de dominio (que parece ser) sin sentido. Puede solucionar estos casos creando una copia local de bar en la parte superior de foo(). Luego, nuevamente, una vez que tenga una copia local del original bar, puede elegir la forma que más le guste.

Por lo tanto, esto es cuestión de gustos. Sí, podría desperdiciar un poquito de memoria para referencia local en el primer caso, pero lo más probable es que JVM lo optimice para que parezca de 2da vía en el nivel de código byte.

3

No está utilizando más memoria en el primer ejemplo, porque String es un objeto inmutable. Como tal, cualquier referencia a una Cadena es simplemente un puntero al mismo objeto en la memoria.

La última opción también tiene algunos problemas de seguridad de subprocesos, donde el resultado de getName() puede cambiar entre invocaciones. Aunque posiblemente sea poco probable, es algo que quizás desee tener en cuenta.

Teniendo esto en cuenta, recomendaría la primera opción aunque sea más "hablante".

Nota: También es posible que getName() se genere por cálculo, en cuyo caso, en realidad terminaría con el segundo método que utiliza más memoria que el primero.

+0

Por lo tanto, en el primer escenario, tanto String name como bar.getName() apuntan a la misma cadena en la memoria. Si cambio bar.name, en realidad no lo estoy cambiando, sino apuntando a otro String, mientras que String name seguirá apuntando al antiguo valor? – user1581900

+1

Eso es correcto. Esta es la razón por la cual todos los métodos en java.lang.String devuelven una nueva Cadena en lugar de modificar el objeto al que están siendo llamados. –

Cuestiones relacionadas