18

我只是好奇。有没有办法访问另一个匿名类中的匿名类中的父级?

我让这个例子创建了一个JTable子类(匿名类)覆盖changeSelection,并在里面创建了另一个匿名类。

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 

我该如何参考super.changeSelection(..)

4

4 回答 4

13

不幸的是,您必须为外部匿名类命名:

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 
于 2013-08-05T20:08:27.450 回答
4

在您的上下文中,“super”当然是指 Runnable 基础,而不是 JTable 基础。如您所知,在内部类中使用“super”是指该内部类的超类,而不是其封闭类的超类(它是否匿名无关紧要)。由于要调用 JTable 基础的方法,因此必须在 JTable 子类方法之一的上下文中使用“super”。

您可以在您的 JTable 子类中创建一个新方法,例如 jTableBaseChangeSelection(),它调用您打算调用的 JTable 的 changeSelection()。然后你从 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

请注意,此答案试图保留您对匿名封闭类的原始设计。这样做肯定是有原因的(是的,在某些情况下,快速组合一些代码一个正当的理由)。有一些孤立的情况发生这种情况——没有造成伤害;但是,如果您发现自己经常遇到这种情况,您可能仍希望重新考虑您的设计。

于 2013-08-05T16:34:29.250 回答
2

我认为您可以创建外部引用并在匿名内部使用它。至少这对我来说适用于 JDK 1.7 和 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 
于 2017-05-08T23:35:12.750 回答
0

我认为下面的代码将完成技术上的要求。也就是说,当有更简单的选择时,我不建议走这条路。

我相信你会希望你的 run 方法做一些比 print "Hello World!" 更有趣的事情。在无限循环中,但这对于概念验证来说似乎没问题。

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);

    }

}
于 2013-08-05T18:05:01.577 回答