【问题标题】:How can you pass in an actual method as a parameter to another method in Java?如何将实际方法作为参数传递给 Java 中的另一个方法?
【发布时间】:2012-05-18 13:35:04
【问题描述】:

我想要做的是轻松地将实际方法对象传递给另一个方法。这样我就可以创建一个通用的 Joiner 函数,该函数在对象列表的给定方法上进行连接,而无需传入表示该方法的字符串。这在 Java 中是否可行,以便我可以使用如下语法:

joinOnMethod(String, Collections<T>, Method) e.g. 
joinOnMethod(", ", someList, T.getName())

其中 T.getName() 将 getName() 方法传递给列表中的每个对象调用,而不是传递方法本身的返回类型。

希望这对我的需求足够清楚,

阿列克谢蓝。

【问题讨论】:

    标签: java generics methods


    【解决方案1】:

    Java 中没有直接的一流函数支持。两种选择:

    • 传入方法的名称,并使用反射来获取它
    • 使用单个成员创建类型,如下所示:

      public interface Function<In, Out> {
          Out apply(In input);
      }
      

      然后你可以使用匿名内部类,像这样:

      joinOnMethod(", ", someList, new Function<T, String>() {
                       @Override public String apply(T input) {
                           return input.getName();
                       }
                   });
      

      当然,您可以将该函数提取为变量:

      private static Function<T, String> NAME_EXTRACTOR = 
          new Function<T, String>() {
              @Override public String apply(T input) {
                  return input.getName();
              }
          };
      
      ...
      
      joinOnMethod(", ", someList, NAME_EXTRACTOR);
      

    【讨论】:

    • Drive-by downvoter:发表评论,解释您认为此答案有什么问题。如果你有一个有效的观点,我相信乔恩会改进他的答案。但最有可能的是,你会从解释你的误解中受益。
    • Jon 的优秀答案(你似乎回答了我所有的 Java 问题 ^.^)。这会很棒,但我最终会为每种方法创建数千个,因为代码库很大,哈哈。我希望 Java 在某个时候对此提供一些支持 :)
    • @AlexeiBlue:Java 8 将对此提供更多支持,但我怀疑您会发现您不会真的 像您想象的那样需要它。一些精心挑选的、公开此类功能的常用只读字段可能对您有很大帮助。
    【解决方案2】:

    我建议研究 Java 中的命令模式。它支持回调功能。

    http://en.wikipedia.org/wiki/Command_pattern#Java

    【讨论】:

    • 对...虽然其他语言有函数指针委托,但Java通过实现接口来处理。
    • 我宁愿处理接口而不是 C 的函数指针。什么样的恶梦。代表要好一些。
    • 很抱歉您对函数指针有不好的体验。接口只不过是一个函数指针表。如果你需要一大堆方法,语言支持很好。但是对于单个函数,必须定义一个接口,然后一个实现它的类是很笨重的。
    • @Ben Voigt 有一次我花了一周时间解决堆栈损坏问题,因为第三方软件包开发人员没有通知我们函数更改,所以现在指针错误并且总是覆盖堆栈(显然没有任何错误)。
    • 听起来像是危险且不必要的强制转换的问题,而不是函数指针的问题。只有一个地方应该在函数指针上使用强制转换:GetProcAddress (Windows) 和 dlsym (Posix) 的返回值。
    【解决方案3】:

    我敢打赌,您刚刚从 Javascript 或其他将函数视为对象的语言迁移到 Java。据我所知,这是不可能的,因为 Java 不将函数视为对象。您必须在 for 循环或其他构造中实际写出它。

    【讨论】:

    • 不,我还没有从 Javascript 迁移过来,哈哈,我只是对这些概念有点陌生,但无论如何感谢你的回答 :)
    • 没问题。我从 Java 转到 Javascript,将函数作为参数传递的想法让我大吃一惊。如果有帮助,请不要忘记 +1 答案,即使您不接受也是如此。
    • 确实没问题 +1 ^.^
    【解决方案4】:

    不,没有这样的语法。此外,由于类型擦除,实际类型T 在运行时不可用,因此即使语法可用,它也不可能在泛型中。

    诀窍是将Class&lt;T&gt;与其他参数一起传递,并使用反射获取方法:

    joinOnMethod(String separator, Collections<T> items, String methodName, Class<T> theClass)
    

    现在您可以在类中查询方法methodName,并在计算中使用该方法。这并不能帮助您避免传递字符串(即当方法不存在时编译器不会触发错误),但您可以使其与泛型一起使用,尽管类型擦除。

    【讨论】:

    • 不幸的是,这就是我想要避免的一点,即将方法名称作为字符串传递。使用反射时可能会很危险,并且您在类中更改名称,因为重构工具不会选择它:/我必须为此考虑一些聪明的东西:)
    猜你喜欢
    • 2018-08-08
    • 2013-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-21
    相关资源
    最近更新 更多