Java8中功能接口的用途

And*_*ejs 5 java java-8 functional-interface

关于Java8 内置功能接口,我遇到过很多问题,包括this,this,thisthis.但所有人都在问"为什么只有一种方法?" 或"如果我使用我的功能界面执行X,为什么会出现编译错误"等等.我的问题是:当我在自己的界面中使用lambda时,这些新功能接口的存在目的什么

请考虑以下来自oracle文档的示例代码:

    // Approach 6: print using a predicate
     public static void printPersonsWithPredicate(List<Person> roster, 
                                                  Predicate<Person> tester) {
            for (Person p : roster) {
                if (tester.test(p)) {
                   System.out.println(p);
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

好的,很好,但这可以用上面的自己的例子来实现(一个单一方法的接口并不新鲜):

      // Approach 5: 
        public static void printPersons(<Person> roster, 
                                        CheckPerson tester) {
            for (Person p : roster) {
                if (tester.test(p)) {
                   System.out.println(p);
                }
            }
        }


  interface CheckPerson {
        boolean test(Person p);
    }
Run Code Online (Sandbox Code Playgroud)

我可以将lambda传递给两个方法.

第一种方法为我节省了一个自定义界 是这个吗?

或者这些标准功能接口(消费者,供应商,谓词,功能)是否可以作为代码组织,可读性,结构,[其他]的模板?

sli*_*lim 5

虽然你问"是吗?",但是我们不需要在我们想要lambda类型的时候编写新接口,这是非常好的.

问问自己,如果您正在阅读API,这对程序员来说更容易使用:

public void processUsers(UserProcessor userProcessor);
Run Code Online (Sandbox Code Playgroud)

... 要么 ...

public void processUsers(Consumer<User> userProcessor);
Run Code Online (Sandbox Code Playgroud)

对于前者,我必须去看看UserProcessor它是什么,以及我如何创造一个; 我甚至不知道它可以作为一个lambda实现,直到我去找出来.对于后者,我立即知道我可以键入u -> System.out.println(u),我将通过将它们写入stdout来处理用户.

另外库的作者没有需要他们臃肿库,另一种类型.

另外,如果我将lambda强制转换为Functional Type,我可以使用该类型的组合方法,例如:

 candidates.filter( personPredicates.IS_GRADUATE.negate());
Run Code Online (Sandbox Code Playgroud)

这使你Predicate的方法and(),or(),negate(),Function方法compose(),andThen()- 除非您实现它们,否则您的自定义类型不会有.

  • 虽然我同意JDK内置通过为我们建立一个通用词汇来帮助我们进行沟通,但我也认为自定义界面的一些例子实际上非常好用.例如,一个`Callback <T>`对我来说比'Consumer <T>`更多.当然,这不是普遍的.那个,并且没有内置的arity超过2的接口(并且2的arity有非常奇怪的选择). (2认同)

M. *_*rov 5

显然,您可以跳过使用这些新接口并使用更好的名称推出自己的接口。但是有一些考虑:

  1. 除非您的自定义接口扩展了内置程序之一,否则您将无法在某些其他 JDK API 中使用自定义接口。
  2. 如果你总是用自己的名字滚动,在某些时候你会遇到一个你想不出好名字的情况。例如,我认为CheckPerson就其目的而言,这并不是一个好名字,尽管这是主观的。

大多数内置接口还定义了一些其他 API。例如,Predicate定义or(Predicate)and(Predicate)negate()

Function定义andThen(Function)compose(Function)等。

它并不是特别令人兴奋,直到它是:在函数上使用抽象方法以外的方法可以更容易地组合、策略选择等等,例如(使用本文中建议的样式):

前:

class PersonPredicate {
  public Predicate<Person> isAdultMale() {
    return p -> 
            p.getAge() > ADULT
            && p.getSex() == SexEnum.MALE;
  }
}
Run Code Online (Sandbox Code Playgroud)

可能会变成这样,最终更可重用:

class PersonPredicate {
  public Predicate<Person> isAdultMale() {
    return isAdult().and(isMale());
  }

  publci Predicate<Person> isAdultFemale() {
    return isAdult().and(isFemale());
  }

  public Predicate<Person> isAdult() {
    return p -> p.getAge() > ADULT;
  }

  public Predicate<Person> isMale() {
    return isSex(SexEnum.MALE);
  }
  public Predicate<Person> isFemale() {
    return isSex(SexEnum.FEMALE);
  }
  public Predicate<Person> isSex(SexEnum sex) {
    return p -> p.getSex() == sex;
  }
}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

715 次

最近记录:

8 年,5 月 前