tipos son que nombre los llevan internas interna interfaz funciones estaticas cuáles compuestas clases clase anonimas anonima anidadas java anonymous-class

java - son - Accede a la clase anónima externa desde la clase anónima interna



que clases internas no llevan nombre (4)

Creo que el siguiente código hará lo que técnicamente se está pidiendo. Dicho esto, no recomendaría seguir esta ruta cuando hay opciones más simples disponibles.

Estoy seguro de que querrá que su método de ejecución haga algo más interesante que imprimir "¡Hola mundo!" en un bucle infinito, pero esto parecía bien para una prueba de concepto.

package test; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import javax.swing.JTable; import javax.swing.SwingUtilities; public class GetOuterAnonymousClass { public static void main(String args []){ JTable table = new JTable(){ @Override public void changeSelection( final int row, final int column, final boolean toggle, final boolean extend) { Runnable runnable = new Runnable() { private Object caller; public void setCaller(Object caller){ this.caller = caller; } @Override public void run() { System.out.println("Hello World!"); try { Class clazz = this.getClass().getEnclosingClass(); Method method = clazz.getDeclaredMethod("changeSelection", new Class[]{Integer.TYPE, Integer.TYPE, Boolean.TYPE, Boolean.TYPE}); method.invoke(caller, 1, 1, true, true); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }; Method method; try { method = runnable.getClass().getDeclaredMethod("setCaller", new Class[]{Object.class}); method.invoke(runnable, this); } catch (SecurityException e1) { e1.printStackTrace(); } catch (NoSuchMethodException e1) { e1.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } SwingUtilities.invokeLater(runnable); } }; table.changeSelection(1, 1, true, true); } }

Tengo curiosidad. ¿Hay alguna manera de acceder a los padres en una clase anónima que esté dentro de otra clase anónima?

Hago que este ejemplo cree una subclase de JTable (clase anónima) que anule a changeSelection y en mi interior creo otra clase anónima.

MCVE:

public class Test{ public static void main(String args []){ JTable table = new JTable(){ @Override public void changeSelection( final int row, final int column, final boolean toggle, final boolean extend) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { super.changeSelection(row, column, toggle, extend); //more code here } }); } }; }//end main }//end test

¿Cómo puedo referirme a super.changeSelection(..) ?


Creo que puedes crear una referencia externa y usarla en tu interior anónimo. Al menos eso me funciona en JDK 1.7 y JDK 1.8.

public class Test{ public static void main(String args []){ class Foo extends JTable { @Override public void changeSelection( final int row, final int column, final boolean toggle, final boolean extend) { final Foo outer = this; // reference to itself SwingUtilities.invokeLater(new Runnable() { @Override public void run() { outer.changeSelection(row, column, toggle, extend); //more code here } }); } }; JTable table = new Foo(); }//end main }//end test


Desafortunadamente, tendrá que dar un nombre a la clase anónima externa:

public class Test{ public static void main(String args []){ class Foo extends JTable { @Override public void changeSelection( final int row, final int column, final boolean toggle, final boolean extend) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { Foo.super.changeSelection(row, column, toggle, extend); //more code here } }); } }; JTable table = new Foo(); }//end main }//end test


En su contexto, ''super'', por supuesto, se refiere a la base de Runnable, no a la base de JTable. Como saben, el uso de ''super'' en una clase interna se refiere a la superclase de esa clase interna, no a la superclase de su clase adjunta (no importa si es anónimo o no). Como desea llamar a un método de la base de JTable, debe usar "super" en el contexto de uno de los métodos de subclase de JTable.

Podría crear un nuevo método en su subclase JTable, por ejemplo, jTableBaseChangeSelection (), que llama a changeSelection () de JTable al que pretende llamar. Entonces llamas a eso desde la subclase Runnable:

public static void main(String args []){ JTable table = new JTable(){ // calls JTable''s changeSelection, for use by the Runnable inner // class below, which needs access to the base JTable method. private void jTableBaseChangeSelection (int row, int column, boolean toggle, boolean extend) { super.changeSelection(row, column, toggle, extend); } @Override public void changeSelection( final int row, final int column, final boolean toggle, final boolean extend) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { // call JTable base changeSelection, since we don''t have access // to the JTable base class at this point. jTableBaseChangeSelection(row, column, toggle, extend); //more code here } }); } }; }//end main

Tenga en cuenta que esta respuesta está intentando conservar su diseño original de una clase anónima adjunta. Ciertamente hay razones para hacerlo (y sí, armar un código rápidamente es una razón válida en algunos casos). Tener algunas situaciones aisladas donde esto sucede, no hay daño; sin embargo, es posible que aún desee replantearse su diseño si se encuentra en situaciones como esta a menudo.