【问题标题】:Calling a function without doing a new调用一个函数而不做一个新的
【发布时间】:2016-11-02 14:45:40
【问题描述】:

我用Java写了一个排序函数和类:

public class MiscellaneousUtilities {

    /**
     * Changes a list of "First Last" to "Last, First" and "First Middle Last" to "Last, First Middle", etc.
     */
    public static Function<String, String> ToLastFirstFunction = new Function<String, String>() {
        @Override
        public String apply(String nm) {
            String[] nmarr = nm.split(" ");
            int last = nmarr.length - 1;
            String res = nmarr[last];
            if (last > 0) {
                res += ",";
            }

            for (int i = 0; i < last; i++) {
                res += " " + nmarr[i];
            }

            return res;
        };
    };
}

当我想使用它时,我不能只说MiscellaneousFunctions.ToFirstLastFunction()

我必须做一个新的MiscellaneousFunctions().ToFirstLastFunction;

我尝试将 static 放在类声明的前面,但它只允许 public、final 和 abstract。如果我想使用Math.min(),请查看数学课,我不必创建新的Math().min()。数学也被定义为前面没有static的类,min()ToFirstLastFunction一样,所以我不明白区别。

【问题讨论】:

  • MiscellaneousFunctions.ToFirstLastFunction() 不起作用,但 MiscellaneousFunctions.ToFirstLastFunction.apply("foo") 应该。
  • 您实际创建的是Function 类型的静态变量,而不是像Math.min() 这样可以调用的方法,如果将ToLastFirstFunction 更改为实际函数,则可以像@ 一样调用它987654334@

标签: java function static


【解决方案1】:

那是因为您必须像这样使用 apply 调用该函数:

MiscellaneousFunctions.ToFirstLastFunction.apply("yourstring");

您可以添加另一个 static 函数作为简写:

public static String toFirstLast(String str) {
    return ToLastFirstFunction.apply(str);
}

Math.min 与您的解决方案之间的主要区别在于,Math.min 是常规的 static 方法,而您有一个 Function 对象,并且可以使用 apply 调用这些方法。

【讨论】:

    【解决方案2】:

    Math.min() 是一个方法 不是函数,在Math.class 中声明如下:

    public int min(int a, int b) {
        ...
    }
    

    ...像这样的方法,您可以像在int x = Math.min(3,2) 中那样直接调用。

    您创建了一个名为ToLastFirstFunctionpublic static 类变量——这不是您可以像方法一样调用的东西。但是您可以使用java.util.function.Function 接口中的方法来处理它——最简单的是apply()

    String out = MiscellaneousFunctions.toFirstLastFunction.apply("John Doe");
    

    (我更改了标识符的大小写——了解 Java 大写约定)


    不是这种情况,您可以使用new MiscellaneousFunctions().toFirstLastFunction("John Doe") 调用您的public static Function&lt;...&gt; -- 我不知道您为什么这么认为。

    可以new MiscellanousFunctions().toFirstLastFunction.apply("John Doe")——但是你的编译器应该警告你通过实例访问static变量。 MiscellanousFunctions.toFirstLastFunction.apply() 是正确的方式。


    所以对您的问题的简短回答是:如果您想以这种方式调用它,请将其编写为方法。


    但如果是这样的话,为什么你将操作定义为一个函数,而不是一个方法?

    嗯,函数的好处是,与方法(*)不同,它们是对象——因此您可以传递它们,将它们放入集合中,将它们分配给变量。他们有像compose()andThen() 这样的方法,它们返回一个新函数,将这个函数与另一个函数结合起来。

    所以你可以这样做:

    Map<String,Function<String,String> nameTranslationStrategies = new HashMap<>();
    nameTranslationStrategies.put(
       "no change", x -> x);
    nameTranslationStrategies.put(
       "to first-last", 
       MiscellaneousFunctions.toFirstLastFunction);
    nameTranslationStrategies.put(
       "capitalised first-last",
       MiscellaneousFunctions.toFirstLastFunction
            .andThen( s -> s.toUpperCase());
    
    ...
    
    String nameTranslationOption = config.getProperty("nameTranslationOption");
    String name = nameTranslationStrategies
         .get(nameTranslationOption)
         .apply(inputString);
    

    Java 程序员几十年来都没有这个特性——直到 Java 8 才出现函数。但是你可以用它们做很多巧妙的事情。

    即便如此,这不是将代码编写为绑定到静态变量的Function 的理由,因为您可以使用:: 语法将普通方法作为函数访问:

      Function<Double,Double> logarithm = Math::log;
      double x = logarithm.apply(2.0);
    

    另请注意,您使用了冗长的语法来定义您的函数:

     public static Function<String, String> slimify = new Function<String, String>() {
        @Override
        public String apply(String s) {
             return "slim says " + s;
        }
     }
    

    ...可以写成:

    public static Function<String,String> slimify = s -> {
        return "slim says " + s;
    }
    

    ...甚至(因为这是单线)

    public static Function<String,String> slimify = s -> "slim says " + s;
    

    了解冗长的方法很好,因为它显示了函数在幕后的工作方式。但在现实世界的代码中,更短的形式是要走的路,因为它更具表现力:代码的意图不会被混乱所掩盖。这是一种表达函数的快速简单的方法,人们经常使用它们而不是将它们分配给变量——就像我在上面的地图示例中所做的那样。


    (*) 我说过方法不是对象。这并非完全正确——部分原因是您可以使用:: 将其作为对象获取,还因为您可以使用Java 的反射API 将类和方法作为对象进行访问。但是你不想使用反射,除非你真的知道你需要。

    【讨论】:

      【解决方案3】:

      Math.min() 是一个名为minpublic static 方法,您的Function 是一个Function 对象,它不是一个方法。您的对象有一个方法apply,您必须使用该方法来实现您想要实现的目标,如下所示:

      MiscellaneousFunctions.ToFirstLastFunction.apply(something)

      【讨论】:

        猜你喜欢
        • 2016-05-13
        • 2011-09-28
        • 2019-12-13
        • 1970-01-01
        • 2019-01-28
        • 2016-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多