【问题标题】:Java Functional Interface with one argument can apply to no argument method?一个参数的Java功能接口可以应用于无参数方法吗?
【发布时间】:2020-10-21 01:35:46
【问题描述】:

参考文献


这是Predicate 功能接口的抽象方法。它得到一个参数T t 并返回boolean

boolean     test​(T t)  
    Evaluates this predicate on the given argument.

但是,在这个例子中,String::isEmpty 没有得到任何参数,而是String 的实例方法。

Predicate<String> p = String::isEmpty;

我可以推断,在 Java 中,这种类型的方法可以应用于具有一个参数的功能接口。

还有,有没有一个参数的函数接口的例子,函数只有一个参数,不像上面的例子?

【问题讨论】:

  • 你错了 String::isEmpty 不是一个标准的谓词......不接受单个参数。它将正在测试的字符串作为其单个参数。相当于 lambda (String s) -&gt; !s.isEmpty()
  • "..有没有一个参数的函数接口与函数有一个参数不像上面的例子?"类似Predicate&lt;String&gt; isA = "A"::equalsIgnoreCase;?
  • @Pshemo - 实际上,这是朝着另一个方向发展。这证明 Predicate 可以采用零参数。那不是我的观点。我的观点只是 String::isEmpty 不是这种情况。
  • @Steve 对不起,但我不确定你的意思(现在可能太累了)。无论如何,我的猜测是 OP 正在询问采用一个参数的方法示例,因为 isEmpty 没有采用我的 suggestionequalsIgnoreCase 采用一个参数。
  • @Pshemo - 我刚刚意识到这不是“零参数”的情况,因为它仍然需要一个字符串作为输入来测试“A”。但是,我没有意识到您可以这样做...使用一个采用单个参数的方法(除了接收器字符串之外),然后显式指定接收器字符串。太酷了!

标签: java


【解决方案1】:

谓词可以采用三种形式。在这里,它们用于字符串上的isEmpty

1- 正式的功能接口:

Predicate<String> somePredicate = new Predicate<String>() {
    @Override
    public boolean test(String s) {
        return s.isEmpty();
    }
};

2- 一个 lambda:

(String s) -> s.isEmpty()

3- 方法参考

String::isEmpty

它们具有相同的功能,并且可以在需要Predicate&lt;String&gt; 时传递。

如果底层函数不是对象上的方法,则第三个不适用。

【讨论】:

    【解决方案2】:

    您可以使用Function&lt;T, R&gt;,其中R 是返回类型,T 是参数类型。
    所以R result = fnc.apply(k) 其中k 的类型是T

    Function<Integer, List<Integer>> fnc =  n-> new ArrayList<>(List.of(n));
    List<Integer> list = fnc.apply(23);
    System.out.println(list);
    

    打印

    [23]
    

    但您也可以这样做,就像在您的示例中一样。

    Function<Integer, List<Integer>> fnc2 = fnc::apply;
    fnc2.apply(44); // returns a list which contains 44
    

    额外细节

    考虑下面的类。一种静态方法和一种实例方法。

    class TestClass {
        public int prod(int a) {
            return a * 33;
        }
        
        public static int mult(int a) {
            return a * 44;
        }
    }
    

    要为静态创建 Lambda,请执行以下操作:

    // use unaryOperator since return type are argument are the same
    UnaryOperator<Integer> fnc = TestClass::mult;
    int result = fnc.apply(10); // returns 440
    

    现在做一个实例版本。

    UnaryOperator<Integer> inst = tc::prod;
    inst.apply(10);
    result = inst.apply(10); // returns 330
    

    现在是使用静态类型引用的特殊情况。
    到一个实例方法。

    
    // This requires 2 arguments. The instance
    // and the argument to the method.a
    
    BiFunction<TestClass, Integer, Integer> stat = TestClass::prod
    result = stat.apply(tc, 12); // result is 396
    

    【讨论】:

    • :: 不仅可以用于类名吗?我对Function&lt;Integer, List&lt;Integer&gt;&gt; fnc2 = fnc::apply; 有另一个困惑。你能进一步解释一下吗?
    • 只是在功能接口中分配apply方法的方法引用。您可以为静态方法使用类名,为实例方法使用实例。
    • 感谢您的详细回答。 @WJS BiFunction&lt;TestClass, Integer, Integer&gt; stat = TestClass::mult 应固定为 TestClass::prod。 @Steve 的回答更适合我原来的问题,但是你的回答对于 Java 功能接口新手来说有更多更好的信息。
    猜你喜欢
    • 2020-07-12
    • 1970-01-01
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    • 2019-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多