2011-01-27 22 views
7

¿Las clases internas son más livianas que las normales, o al final Java compila las clases internas al igual que las clases normales?¿Las clases internas son livianas?

Sé que las clases en Java no son todas muy ligeras, y ocupan parte de la memoria permgen, por lo que me gustaría saber si es mejor usar funciones de cierre como clases internas, o si las clases estándar también está bien?

+1

La JVM solo tiene tipos de datos primitivos ('int',' float', etc.) y clases. No hay nada entre ellos. – Gabe

Respuesta

17

Las clases internas y las clases internas anónimas compilan hasta los archivos .class. Por ejemplo:

class Outer { 
    class Inner { 

    } 

    Object function() { 
      return new Object() { 

      }; 
    } 
} 

generará tres archivos, .classOuter.class, Outer$Inner.class y Outer$1.class. No son más "ligeros" que otras clases, y (a lo mejor de mi conocimiento) no hay ventaja de usar uno sobre el otro desde una perspectiva de rendimiento. Por supuesto, las clases internas y especialmente las clases internas anónimas son realmente útiles en contextos donde las clases regulares son más difíciles de codificar, pero eso es un problema aparte.

+7

+1. Si algo las clases internas son "más pesadas" porque contienen métodos sintéticos y campos que el compilador crea para facilitar las reglas especiales de visibilidad que tienen con respecto a su clase contenedora. – Thilo

+0

¡Guau! Gracias por la info! – Waneck

1

No son livianos, pero tienen límites. AFAIK, no puedes crear más de una instancia de una clase interna anónima, y ​​si tus necesidades lo requieren, debes usar una clase no anónima.

edit 1: Gracias por todos los comentarios y aclaraciones. Ayúdenme a entender esto mejor ... Entiendo que puede tener varias instancias de clases internas anónimas, pero si declaro un objeto ActionListener interno anónimo, por ejemplo, ¿cómo puedo tener varias instancias de que clase y solo esa clase? sin usar el reflejo? Gracias de antemano (¿o debería preguntar esto en mi propia pregunta?)!

OK, ya que no estoy recibiendo ningún bocado ... Déjame demostrar con el código. Digo creo un ActionListener anónima aquí:

JButton button = new JButton("Button"); 

    button.addActionListener(new ActionListener() { 
    @Override 
    public void actionPerformed(ActionEvent arg0) { 
     System.out.println("Button says \"Foo!\""); 
    } 

    }); 

    JOptionPane.showMessageDialog(null, button); 

puedo crear un ActionListener anónima y también crear un objeto de esta clase de un solo golpe. Lo que siempre me han enseñado, lo que mencioné en la parte superior de mi post aquí (y se me despertó), fue que es difícil, si no imposible (sin la magia de la reflexión) hacer otro objeto de esta clase anónima, que solo se puede hacer un objeto, y en situaciones donde solo se necesita un objeto, está bien. Pero en otras situaciones, no está bien. Y, por supuesto, se podría crear múltiples clases ActionListener anónimos similares, como en un bucle for:

JPanel panel = new JPanel(new GridLayout(5, 5)); 
    JButton[] buttons = new JButton[25]; 
    for (int i = 0; i < 25; i++) { 
    final int btnNumber = i; 
    buttons[i] = new JButton(String.valueOf(btnNumber)); 
    buttons[i].addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      System.out.println("From button " + btnNumber); 
     } 
    }); 
    panel.add(buttons[i]); 
    } 
    JOptionPane.showMessageDialog(null, panel); 

Pero aún así, cada clase anónima creada aquí es diferente. Esto puede tener importancia si este mismo tipo de oyente es utilizado por múltiples JButtens, tiene estado y su comportamiento depende de este estado. ¿De acuerdo? ¿Discrepar? ¡Gracias por adelantado por cualquier contribución!

+3

Puede tener múltiples instancias de clases internas anónimas, por ejemplo, colocando la clase en un bucle 'for' y creando instancias múltiples veces.Creo que Java requiere que todas estas clases tengan el mismo tipo, pero no recuerdo si eso es correcto o no. – templatetypedef

+1

Estás pensando en ello. Una clase interna anónima sigue siendo una clase. Puedes tener tantas instancias como quieras. También puede tener tantas clases internas anónimas como desee. El compilador maneja todo esto en tiempo de compilación. La primera especificación anónima que encuentra obtiene el encantador nombre de Foo $ 1, el segundo es Foo $ 2, y así sucesivamente. El código como 'new Runnable() {...}' se convierte en 'Foo.new 1()'. –

+0

¡Gracias por los comentarios y la información útil! Por favor, aclare para mí ... si tengo un ActionListener interno anónimo, ¿cómo puedo tener dos instancias distintas de esta clase (sin reflexión) ya que es crear cuando se crea el objeto? Sé que puedo tener muchas instancias de ActionListeners anónimos, pero me pregunto cómo es posible tener varias instancias de una clase anónima distinta que se haya declarado. –

7

Las clases internas todavía son clases y todavía tienen que ser cargadas por un ClassLoader. En todo caso, lo contrario es cierto. Una clase interna no estática puede evitar que la clase padre sea recogida como basura, ya que tiene una referencia a la clase que lo posee.

+1

+1. Además de la referencia principal, también hay métodos sintéticos que permiten llamar a métodos "privados" de las clases relacionadas. – Thilo

Cuestiones relacionadas