【问题标题】:Java Methods - Taking a method AS AN ARGUMENTJava 方法 - 将方法作为参数
【发布时间】:2009-05-20 11:43:24
【问题描述】:

我遇到了一些无法在此处分享的代码,但它声明一个方法WITHIN另一个方法的参数列表。我什至不知道这是可能的。我真的不明白它为什么这样做。有人可以向我解释一下您作为程序员可能会这样做的用途吗? (注意:由于我无法显示代码,因此我一般不期望有上下文解释)

相关:

What's the nearest substitute for a function pointer in Java?

【问题讨论】:

  • 能否展示一个语法示例,而不是代码本身,而是使用相同构造的 MethodWithMethodArgs,以及调用该方法的示例?

标签: java methods


【解决方案1】:

代码看起来像这样吗?

obj.someMethod(myVar,3,new FooObject() {
  public void bar() {
    return "baz";
  }
});

如果是这样,则该方法不会作为参数传递给另一个方法,而是会创建一个anonymous inner class,并且该类的一个实例作为参数传递。

在上面的例子中,FooObject 是一个抽象类,它没有实现bar() 方法。我们不是创建一个扩展FooObjectprivate class,而是创建一个抽象类的实例,并提供与其余代码一致的抽象方法的实现。

您不能创建抽象类的实例,因此我们必须提供缺少的方法来创建完整的类定义。由于这个新类是动态创建的,因此它没有名称,因此 匿名。因为它是在另一个类中定义的,所以它是一个匿名的 inner 类。

它可能是一个非常方便的快捷方式,尤其是对于Listener 类,但如果您忘乎所以并且行内方法定义太长,它会使您的代码难以遵循。

【讨论】:

  • 有点像,除了 FooObject 实际上是一个已经存在于其他地方的抽象类,所以它不是匿名内部类吗?
  • 是的,它将是匿名的,匿名的父类是 FooObject。
  • 我开始认为你可能是对的。但是,其他人说可以通过反思呢?
  • 如果传入的对象是Method类型,那么是的,那么就是通过反射来完成的。
【解决方案2】:

在 Java 中,您不能将方法作为参数传递。难道它传递的不是一个方法,而是一个匿名的内部类?

这对于在类之间传递行为很有用。谷歌“依赖注入”或“控制反转”了解更多信息。

【讨论】:

  • 我很确定它不是匿名内部类,因为它以 public void name() { } 等开头
  • 嗯,从技术上讲,你可以传递一个 Method 对象。
【解决方案3】:

你见过Functional Java吗? 这是一个非常有趣的库,可让您像在Scala 中一样进行编程。 I Wrote 关于这个库。我承认最好使用更灵活的语法(BGGA 闭包),比如 Scala。

在我们拥有的列表上使用具有高阶函数(如 map)的函数式 Java:

final List<Integer> numbers = list(1, 2, 3, 4, 5);  

List<Integer> c = numbers.map(new F<Integer, Integer>() {  
                 public Integer f(Integer arg) {  
                   return arg * arg;  
                  }  
              });  

另一个有用的库是lambdaj,它提供了像函数式(FP)编程一样的好方法。 与 FP 语言相比,Java 的语法有限。但是你仍然可以利用 FP 风格的一些优势,但你必须要有创意!

【讨论】:

  • 澄清一下:看起来你可能会说 Java 7 会有闭包,但实际上并非如此。
  • 不是在 Java 7 中。也许在 Java 8 中(尽管他们可能会称它为 Java 2.0 或其他什么东西,让每个人都感到困惑)。
【解决方案4】:

使用java.lang.reflect.Method

示例

public void callMethod(Method aMethod, int value) throws Exception {
    aMethod.invoke(this, value);
}

public void print(Integer value) {
    System.out.print(value);
}

public void println(Integer value) {
    System.out.println(value);
}

public void demo() throws Exception {
    Method println = this.getClass().getMethod("println", Integer.class);
    Method print = this.getClass().getMethod("print", Integer.class);
    callMethod(println, 10);
    callMethod(print, 10);
}

【讨论】:

  • 我在网上看到过这个。人们说它的反射,有人说它不可能,人们说它是可能的,因为反射。
  • 您可以使用反射将 Method 对象作为参数传递,但不能使用 to 来声明方法,这就是您所说的代码所做的。
【解决方案5】:

在 Java 中传递函数指针最接近的方法是传递抽象类或接口的匿名实例。例如,一个泛型函数类型可以在这样的接口中编码:

public interface F<A, B> {
  public B f(final A a);
}

然后您可以在另一个方法的参数列表中期待一个方法:

public List<B> map(List<A> as, F<A, B> f) {
  ...
}

您可以使用该接口的匿名实例调用它:

map(myList, new F<Integer, String>() {
  public String f(Integer i) {
    return String.valueOf(i);
  }
});

有一个名为 Functional Java 的库正是利用这个想法为光荣的 Java 语言带来了巨大的利益。

【讨论】:

    【解决方案6】:

    它本身不是 Java 中的合法语法。是不是创建了一个匿名类的新实例?

    【讨论】:

      【解决方案7】:

      你也可以这样做:

      final Predicate somePredicate = new Predicate<Item>() 
        {
        @Override
        public boolean apply(Item item)
          {
          return item.someProperty().equals(something);
          }
        }
      

      并像这样使用它:

      List<Item> filteredList = filter(list, somePredicate);
      

      我以前做过类似的事情。我还编写了使用闭包以类似方式构建和返回接口的匿名实现的方法:

      Predicate isSomeColor(final Color color)
        {
        return new Predicate<Shape>() 
          {
          @Override
          public boolean apply(Shape shape)
            {
            return shape.getColor().equals(color);
            }
          }
        }
      
      List<Shape> redShapes = filter(shapes, isSomeColor(Color.RED);
      

      所有这些仍然是匿名的内部类。我实际上没有在任何地方命名类本身,我只是引用了该类的一个实例。

      【讨论】:

        【解决方案8】:

        这被称为reflection。有一个完整的对象库,表示构造函数、方法等。
        例如,您可以使用它来调用在运行时确定的动态method

        【讨论】:

          【解决方案9】:

          是的,可以在另一个方法的参数列表中声明一个方法。您可以查看 java.lang.reflect.Method

          使用反射,您可以检索一个 Method 对象,该对象表示您希望作为参数传递的方法。然后你可以调用 Method 来调用该方法。

          此外,您可以参考“Java 语言中的函数式编程”(http://www.ibm.com/developerworks/java/library/j-fp.html),它可以为您提供由内而外的例子。

          【讨论】:

          • 看到了吗?我很困惑!是反射还是匿名内部类?
          【解决方案10】:

          关于它是否可能,上面的答案各不相同。可以通过反思吗?是否可以通过使用匿名内部类?我们需要澄清这一点。

          【讨论】:

          • 如果你显示语法(你不必显示确切的代码),更容易理解你的意思。
          • 这个问题有点含糊,因为“方法”这个词有一个重载的含义:1)称为方法(java.sun.com/javase/6/docs/api/java/lang/reflect/Method.html)的java反射类型,它是一种可以像任何类型一样传递的类型其他类型,以及 2) 你写的 '...它在参数列表中声明了一个方法...' ,正确的术语是声明一个匿名内部类。很难说你到底指的是哪一个。您可以通过多种方式实现传入“方法”,这是其中的两种。你的确切问题是什么?
          • 好吧,当你问一个关于代码的问题而不显示代码时,你会期待什么?
          • @Diego:可以使用反射(如此处所示:stackoverflow.com/questions/887444/…)或使用匿名内部类(如此处所示:stackoverflow.com/questions/887444/…)。这段代码是什么样的?
          【解决方案11】:

          最接近函数参数的是

          只有一个方法的匿名类的实例。

              Runnable a = new Runnable(){
          
             run(){
              System.out.println("hello");
                  }
              }
          
            myMethod(a);
          

          【讨论】:

            【解决方案12】:

            不是指针,但您仍然可以通过一些技巧内联编写函数。

            在另一个thread 上查看我的answer

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2022-01-22
              • 2016-12-31
              • 1970-01-01
              • 2017-08-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-10-14
              相关资源
              最近更新 更多