2011-01-11 12 views
9

Recientemente me encontré con el siguiente fragmento en una base de código en la que estoy trabajando y agregué el comentario que ves allí. Sé que esta pieza de código en particular se puede reescribir para que sea más limpia, pero me pregunto si mi análisis es correcto.¿Declarar muchas clases idénticas anónimas desperdicia memoria en Java?

Will java crear una nueva declaración de la clase y almacenarlo en la ondulación permanente espacio de generación para cada llamada de este método, o va a saber para reutilizar una declaración existente?

protected List<Object> extractParams(HibernateObjectColumn column, String stringVal) { 
    // FIXME: could be creating a *lot* of anonymous classes which wastes perm-gen space right? 
    return new ArrayList<Object>() { 
     { 
      add(""); 
     } 
    }; 
} 
+0

Pero quizás el uso de una clase interna en lugar de una clase anidada estática desperdicia un poco de memoria para el puntero externo $ this (en caso de que no sea necesario). Eso sería memoria de pila, sin embargo. – Thilo

+0

El código duplicado desordena su código y hace que sea más difícil de mantener, eso debería ser más una preocupación. –

Respuesta

15

La clase solo se compilará una vez (en tiempo de compilación). El compilador extrae una clase (llamada algo así como MyOuterClass$1) y la usa. Creará instancias múltiples, por supuesto, pero todas serán de la misma clase. Puede ver que cuando compila el archivo .java y mira los archivos .class generados, habrá uno para la clase anónima interna.

5

No, eso crea muchos casos de una sola clase. Para probar, poner esto dentro de su clase anónima:

@Override 
public String toString() { 
    return getClass().getName(); 
} 

luego llamar a toString() en diversas instancias de la clase anónima. Verás que todos devuelven el mismo nombre de clase.

3

Las demás respuestas son correctas.

Sin embargo:

  • Si este patrón se repite un número de veces en su código, entonces se terminar con el mismo número de clases internas. Si utiliza el patrón cientos/miles de veces, el aumento del uso de la huella del código/permgen podría ser significativo.

  • Lo que está haciendo en este ejemplo particular se podría expresar más simplemente como

    protected List<Object> extractParams(HibernateObjectColumn column, 
                String stringVal) { 
        return Collections.singletonList(""); 
    } 
    
  • Para los casos donde hay que rellenar la lista con varios valores, una solución que implica un método de ayuda estática es probablemente más sencillo .

+0

ah, tiene sentido, gracias. en este caso particular, probablemente lo reemplace con Arrays.asList ("") ya que Collections.singletonList ("") proporcionará una lista inmutable y es posible que el código del cliente modifique el resultado. – depsypher

+0

Sí - 'Arrays.asList (...)' es una mejor solución. –

+0

@depsypher Sin embargo, recuerde que el resultado de 'Arrays.asList' aún no se puede cambiar de tamaño. Lo único que puede hacer (en este caso) que 'Collections.singletonList' no puede es usar' list.set (0, ...) '. Además, las API son más limpias al devolver listas inmutables.Las personas que llaman realmente deberían clonar la lista cuando quieran modificarla; las copias de la lista superficial no son costosas. –

0

¿El declarando muchas clases de residuos de memoria anónima idénticos en java?

Por supuesto que sí, pero no está haciendo eso en el código que ha publicado.

+0

Él ciertamente está declarando una clase anónima. Creo que la connotación es que él tendrá ese código en muchos lugares. – tster

+0

@tster Exactamente. Él está declarando una clase anónima. No muchos'. Sin connotaciones necesarias. Él está preguntando explícitamente '¿Java creará una nueva declaración de clase y la almacenará en el espacio generador de perm para cada llamada de este método?'. No lo hará. – EJP

Cuestiones relacionadas