usar programacion modificador metodos metodo estaticos diferencia cuando clase java android performance static-classes

programacion - private static final java



¿Por qué Android prefiere clases estáticas (5)

Veo un montón de código Java donde Android prefiere que los desarrolladores usen clases internas estáticas. Particularmente para patrones como el Patrón ViewHolder en Custom ListAdapters.

No estoy seguro de cuáles son las diferencias entre las clases estáticas y no estáticas. He leído sobre esto, pero no parece tener sentido cuando me preocupa el rendimiento o la huella de memoria.


La principal diferencia entre las clases internas estáticas y no estáticas es que una clase interna no estática tiene acceso a otros miembros de la clase externa, incluso si son privadas. Las clases internas no estáticas son una "parte" de la clase externa. No puede crear ni puede existir sin una instancia de una clase externa. Una consecuencia de esto es que una instancia de una clase interna no estática se destruye cuando se destruye la instancia de la clase externa.

Las clases internas estáticas, por otro lado, son como las clases externas normales. Los viven y mueren solos. No necesita una instancia de la clase externa para que exista la clase interna. Eso significa que también tienen su propio ciclo de vida. Se destruyen cuando el recolector de basura decide destruirlos.

¿Cómo afecta esto la memoria y / o el rendimiento? Realmente no lo sé :)


Las clases internas estáticas (es decir, las clases declaradas dentro de otra clase con palabra clave static ) son bastante similares a las clases "normales", excepto que no se contamina el espacio de nombre de su paquete. Esa es su (única) diferencia y beneficio, y creo que esa es la razón por la que lo ves en Android.

Use clases internas estáticas cuando el propósito de la clase es ajustar a la clase principal, pero no depende de sus instancias. Esto generalmente se considera una buena práctica.


No son solo desarrolladores de Android ...

Una clase interna no estática siempre mantiene una referencia implícita al objeto adjunto. Si no necesita esa referencia, todo lo que hace es costar la memoria. Considera esto:

class Outer { class NonStaticInner {} static class StaticInner {} public List<Object> foo(){ return Arrays.asList( new NonStaticInner(), new StaticInner()); } }

Cuando lo compila, lo que obtendrá será algo como esto:

class Outer { Outer(){} public List<Object> foo(){ return Arrays.asList( new Outer$NonStaticInner(this), new StaticInner()); } } class Outer$NonStaticInner { private final Outer this$0; Outer$NonStaticInner(Outer enclosing) { this$0 = enclosing; } } class Outer$StaticInner { Outer$StaticInner(){} }


Si descompilas una clase interna (o la ves usando un depurador) puedes ver que hay código generado para acceder a la instancia de la clase externa que se usó para crearlas. La sobrecarga para esto es más memoria para el puntero adicional, más CPU para la recolección de basura debido a un puntero adicional para probar, y si quiere nit pick, tiempo de compilación más largo. Crear instancias de clases internas no estáticas es un poco más complicado porque necesita una instancia de la clase externa para crearlas.

La visibilidad de las clases internas tanto estáticas como no estáticas se puede controlar. Usualmente son privados si su implementación está fuertemente relacionada con los detalles internos de la clase externa, y el desarrollador no cree que el código pueda ser reutilizado. En este sentido, no son mejores que las funciones privadas. Las clases internas pueden ser públicas en casos como Map.Entry, donde la clase interna está fuertemente conectada a la interfaz expuesta por la clase, y el desarrollador no cree que Map.Entry se pueda usar sin algún tipo de Map. Ambos tipos tienen acceso a miembros privados de la clase externa y la clase externa tiene acceso a miembros privados de la clase interna.

Las instancias de clases internas estáticas y no estáticas se recolectan como cualquier otra clase. No hay una conexión especial entre la colección de grabación de la clase externa y la colección de basura de la clase interna.

En el caso de implementación de clases UI como swing o android, verás clases internas estáticas porque se tratan como funciones privadas. Estas clases no están desarrolladas para su reutilización fuera de la clase externa y están fuertemente conectadas a la implementación interna de la clase externa. No hay ninguna razón para exponerlos y asegurarse de que puedan funcionar en más casos que el contexto específico de los requisitos de la clase externa.


Una instancia de clase interna no estática contiene una referencia a la instancia de clase externa, mientras que una instancia de clase interna estática no.

Esto es relevante para la huella de memoria de las aplicaciones, ya que la referencia oculta puede provocar pérdidas de memoria: el recolector de elementos no utilizados no puede recopilar la instancia de clase externa hasta que no haya más referencias. Además, la referencia adicional en sí misma necesita memoria, esto puede ser relevante si se usa una gran cantidad de instancias.

class Outer{ class Inner{//Only works with non static inner class public Outer getOuter(){return Outer.this;} } }

También es relevante para su uso, la referencia a la clase externa es un argumento ctor de la clase interna, para crear un nuevo objeto de clase interna no estática debe llamar al coordinador como una función miembro en una instancia de la clase externa o desde dentro de una función miembro de la clase externa. Esto significa que no puede tener una instancia de la clase interna sin una instancia de la clase externa.

Outer.Inner in = new Outer().new Inner();