2011-02-10 18 views
11

Cuando tengo clases internas con métodos o campos privados, el compilador tiene que crear métodos de acceso sintéticos protegidos por paquetes para permitir que la clase externa acceda a esos elementos privados (y viceversa).¿Hay una sobrecarga de rendimiento para una clase interna privada en Java?

Para evitar eso, generalmente hago que todos los campos y métodos y constructores estén protegidos por paquetes en lugar de privados.

Pero, ¿qué hay de la visibilidad de la clase en sí? ¿Hay una sobrecarga de

private static class A { 
     A(){} 
} 

frente

static class A { 
     A(){} 
} 

Tenga en cuenta que el constructor es el paquete protegido en ambos casos, o no hacer el cambio de clase privada que?

+1

posible duplicado de [¿Son livianas las clases internas?] (Http://stackoverflow.com/questions/4812464/are-inner-classes-lightweight) – templatetypedef

+0

Me pregunto si la visibilidad reducida se aprovecha de alguna manera con el punto de acceso. También me pregunto si los compiladores de Java pueden usar este hecho para excluir a la clase de consideración fuera de su alcance de visibilidad. Interesante pregunta, pero no creo que haya ningún beneficio práctico. – Ron

+0

@Ron: el compilador/IDE sin duda verificará la visibilidad y realizará errores de compilación o eliminarlos de la función autocompletar. Me pregunto si algo está sucediendo en tiempo de ejecución. – Thilo

Respuesta

16

¿Ha intentado compilarlo y comparar el código de bytes? Aquí están mis resultados. Por:

public class Example { 
    public static void main(String[] args) { 
    System.out.println("Hello world!"); 
    } 
    private static class A { 
    A(){} 
    } 
} 

Lo anterior produce los siguientes archivos * .class:

-rw-r--r-- 1 michaelsafyan staff 238 Feb 10 00:11 Example$A.class 
-rw-r--r-- 1 michaelsafyan staff 474 Feb 10 00:11 Example.class 

Ahora, si muevo los archivos de clase, elimine el modificador private, y recompilar, me sale:

-rw-r--r-- 1 michaelsafyan staff 238 Feb 10 00:15 Example$A.class 
-rw-r--r-- 1 michaelsafyan staff 474 Feb 10 00:15 Example.class 

Si mira el VM Spec on class files, verá que hay un campo de bits de tamaño constante para especificar los modificadores de acceso, por lo que no debería sorprender que los archivos generados sean los mismos tamaño.

En resumen, los modificadores de acceso no afectarán el tamaño del código de bytes generado (tampoco debe tener ningún impacto en el rendimiento). Debe usar el modificador de acceso que tenga más sentido.

También debo añadir que hay una pequeña diferencia si se cambia la clase interna de static a no declarada static, ya que implica un campo adicional que hace referencia a la clase externa. Esto ocupará un poco más de memoria que si declaraste la clase interna static, pero estarías loco por optimizar esto (usa static donde tenga sentido, y donde lo necesites no sea estático, hazlo no estático , pero no convine su diseño solo para guardar un puntero de memoria aquí o allá).

+0

Los Findbugs me dijeron que lo hiciera estático ... – Thilo

+3

@Thilo, eso es porque no hace referencia a nada en la clase externa; si necesita acceder a los miembros o funciones de la clase externa, entonces habría una razón legítima para hacerlo no estático. –

7

No debe haber diferencia de rendimiento entre una clase interna privada y una clase interna no privada.

No debe haber diferencia de rendimiento entre una clase interna estática (privada o no) y una clase externa.

Hay una pequeña diferencia de rendimiento entre una clase interna estática y una clase interna no estática. Esta diferencia se debe al hecho de que el caso no estático tiene una referencia oculta a la instancia de su clase adjunta. Esto se pasa como un parámetro extra al constructor de clases internas, y se almacena en una variable oculta.

+1

Y (para cubrir todos los casos) también hay una pequeña diferencia de rendimiento al omitir la visibilidad privada (de campos, métodos y constructores) con clases internas. – Thilo

+2

@Thilo - ¿Hay? ¿Por qué? AFAIK, las reglas de visibilidad son impuestas por el compilador y por el verificador. Para cuando se ejecuta (o compila JIT) los códigos de bytes, las comprobaciones de visibilidad se han realizado y no hay impacto en el rendimiento. –

+1

La diferencia de rendimiento proviene del acceso a un método privado a través de un método de envoltura sintética generado por el compilador en lugar de tener acceso directamente a un método protegido por paquete. – Thilo

4

Es muy poco probable que esto pueda causar una desaceleración significativa.

Un problema que debe tenerse en cuenta con las clases internas no estáticas es que contienen una referencia a la instancia de la clase adjunta.

Como tal, esto puede causar "pérdidas de memoria", ya que la instancia adjunta no se puede recoger como basura. Si pasa instancias de clases internas a las personas que llaman, también está distribuyendo una instancia de la clase adjunta.

¡Este no es el caso con las clases internas estáticas!

No es aconsejable proteger todos los campos para evitar los métodos sintéticos. Usted está renunciando a la encapsulación, que es algo valioso que debe tener. ¿Cuáles son sus inquietudes? Tamaño de sus archivos de clase para el código adicional?

+1

La encapsulación es más importante a nivel de paquete, así que no renunciaré mucho aquí. Los paquetes externos (es decir, el código de otras personas) no pueden ver la clase de ninguna manera. – Thilo

+0

@Thilo El hecho de que esto sea así ahora, no necesariamente significa que esto se mantendrá para siempre de esta manera. La encapsulación lo prepara más para lo no planificado que lo esperado. – TheBlastOne

+1

@TheBlastOne: De nuevo, no estoy rompiendo la encapsulación en absoluto aquí. Todo sigue siendo privado del paquete. – Thilo

Cuestiones relacionadas