【问题标题】:How to make a method a parameter for a constructor如何使方法成为构造函数的参数
【发布时间】:2016-11-08 16:29:01
【问题描述】:

在用 Java 制作一个小游戏时,我偶然发现了 keyListener 类,它在实例化时要求三个方法(keyTyped、keyPressed 和 keyReleased),如下所示:

JFrame.addKeyListener(new KeyListener(){
    public void keyTyped(KeyEvent evnt) {
    //blah
    }
    public void keyPressed(KeyEvent evnt) {
    //blah
    }
    public void keyReleased(KeyEvent evnt) {
    //blah
    }
});

我怎样才能得到一个我在自己的接受方法上创建的类作为参数?

【问题讨论】:

标签: java


【解决方案1】:

它不接受方法作为参数。您正在声明一个匿名类并将其作为参数传递给 addKeyListener 方法。

【讨论】:

    【解决方案2】:

    从技术上讲,这些方法在这里不是参数。唯一的参数是 KeyListener 的一个匿名实例。

    KeyListener 是一个interface,需要实现这 3 个方法。

    如果你想定义自己的接口,它看起来类似于一个类:

    public interface SomeInterface {
        public void foo();
        public int bar(int x);
    }
    

    然后你可以匿名使用它(就像在你的例子中一样),或者在一个类中实现它:

    public class MyClass implements SomeInterface {
        // ...
    }
    

    【讨论】:

      【解决方案3】:

      new KeyListener() { ... }实际上创建了一个实现KeyListener的匿名内部类。因此,它可以访问创建它的类的任何可见字段以及调用构造函数的方法中的任何局部 final 变量。

      例子:

      class Outer {
        int x;
      
        void initUI( final int z) {
          final int y = 0;        
          int nope = 1; //you can't access this since it is neither final nor a field like x
      
          JFrame.addKeyListener( new KeyListener() {
            public void keyTyped(KeyEvent evnt) {
              System.out.println( x + y + z ); //you can access all of them
            }
          });
        }
      }
      

      如果你想为你的关键监听器提供一个构造函数,你需要明确定义一个类,如anonymous classes can't have custom constructors。这意味着你必须做这样的事情(注意:伪代码):

      class Outer {
        void initUI() {
          JFrame.addKeyListener( new InnerKeyListener( myParam ) );
        }
      
        class InnerKeyListener implements KeyListener {
          InnerKeyListener( Param p ) {
          }
      
          ...
        }
      }
      

      当然你也可以把内部类放到一个单独的文件中,或者把它变成一个静态的内部类。

      【讨论】:

        【解决方案4】:

        我知道回答我自己的问题很奇怪,但是......

        我想通了。您必须使您的类抽象,并且您可以声明抽象方法以使方法成为“参数”,使其行为类似于 KeyListener 声明。抽象方法声明如下:

            abstract ReturnType name(Parameter p);
        

        并且在调用时的行为与方法完全相同。完整示例:

            //The abstract keyword enables abstract methods to work with this class.
            abstract class Foo {
                //Just a random variable and a constructor to initialize it
                int blah;
                public Foo(int blah) {
                    this.blah = blah;
                }
                //An abstract method 
                abstract void doStuff();
                //Example with a parameter
                abstract void whatDoIDoWith(int thisNumber);
                //A normal method that will call these methods.
                public void doThings() {
                    //Call our abstract method.
                    doStuff();
                    //Call whatDoIDoWith() and give it the parameter 5, because, well... 5!
                    whatDoIDoWith(5);
                }
            }
        

        当您尝试像普通类一样实例化抽象类时,Java 会崩溃。

            Foo f = new Foo(4);
        

        你需要做的是这样的:

            Foo f = new Foo(4) {
                @Override
                void doStuff() {
                    System.out.println("Hi guys! I am an abstract method!");
                }
                @Override
                void whatDoIDoWith(int thisNumber) {
                    blah += thisNumber;
                    System.out.println(blah);
                }
             }; //Always remember this semicolon!
        

        请注意,您需要在此处包含所有抽象方法,而不仅仅是其中的一些。现在,让我们试试这个:

            public class Main {
                public static void main(String[] args) {
                    //Instance foo.
                    Foo f = new Foo(4) {
                        @Override
                        void doStuff() {
                            System.out.println("Hi guys! I am an abstract method!");
                        }
                        @Override
                        void whatDoIDoWith(int thisNumber) {
                            blah += thisNumber;
                            System.out.println(blah);
                        }
                    };
                    //Call our method where we called our two abstract methods.
                    foo.doThings();
                }
            }
        

        这会将以下内容打印到控制台:

            Hi guys! I am an abstract method!
            9
        

        【讨论】:

          猜你喜欢
          • 2014-05-09
          • 2016-01-24
          • 2021-01-08
          • 2021-06-04
          • 2019-03-03
          • 2020-06-02
          • 2011-09-04
          • 2017-02-13
          相关资源
          最近更新 更多