这段代码有什么区别?
Supplier<LocalDate> s1 = LocalDate::now;
LocalDate s2 = LocalDate.now();
System.out.println(s1.get()); //2016-10-25
System.out.println(s2); //2016-10-25
我开始学习 Java 8 中的函数式接口(interface),但不了解供应商的好处。何时以及如何使用它们。供应商是否提高了性能或抽象级别的好处?
感谢您的回答!这不是重复的问题,因为我使用搜索并没有找到我需要的东西。
更新 1: 你是说这个吗?
Supplier<Long> s1 = System::currentTimeMillis;
Long s2 = System.currentTimeMillis();
System.out.println(s1.get()); //1477411877817
System.out.println(s2); //1477411877817
try {
Thread.sleep(3000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(s1.get()); //1477411880817 - different
System.out.println(s2); //1477411877817
最佳答案
我将介绍一个我们应该使用 Supplier<LocalDate>
的场景而不是 LocalDate
.
直接调用静态方法的代码,如 LocalDate.now()
很难进行单元测试。考虑一个场景,我们要对方法进行单元测试 getAge()
计算一个人的年龄:
class Person {
final String name;
private final LocalDate dateOfBirth;
Person(String name, LocalDate dateOfBirth) {
this.name = name;
this.dateOfBirth = dateOfBirth;
}
long getAge() {
return ChronoUnit.YEARS.between(dateOfBirth, LocalDate.now());
}
}
这在生产中运行良好。但是单元测试要么必须将系统的日期设置为已知值,要么每年更新一次以期望返回的年龄增加一个,这两种解决方案都是非常棒的。
更好的解决方案是让单元测试在已知日期注入(inject),同时仍允许生产代码使用 LocalDate.now()
.也许是这样的:
class Person {
final String name;
private final LocalDate dateOfBirth;
private final LocalDate currentDate;
// Used by regular production code
Person(String name, LocalDate dateOfBirth) {
this(name, dateOfBirth, LocalDate.now());
}
// Visible for test
Person(String name, LocalDate dateOfBirth, LocalDate currentDate) {
this.name = name;
this.dateOfBirth = dateOfBirth;
this.currentDate = currentDate;
}
long getAge() {
return ChronoUnit.YEARS.between(dateOfBirth, currentDate);
}
}
考虑这样一个场景:自对象创建以来,这个人的生日已经过去了。通过此实现,getAge()
将基于创建 Person 对象的时间而不是当前日期。我们可以使用 Supplier<LocalDate>
来解决这个问题:
class Person {
final String name;
private final LocalDate dateOfBirth;
private final Supplier<LocalDate> currentDate;
// Used by regular production code
Person(String name, LocalDate dateOfBirth) {
this(name, dateOfBirth, ()-> LocalDate.now());
}
// Visible for test
Person(String name, LocalDate dateOfBirth, Supplier<LocalDate> currentDate) {
this.name = name;
this.dateOfBirth = dateOfBirth;
this.currentDate = currentDate;
}
long getAge() {
return ChronoUnit.YEARS.between(dateOfBirth, currentDate.get());
}
public static void main(String... args) throws InterruptedException {
// current date 2016-02-11
Person person = new Person("John Doe", LocalDate.parse("2010-02-12"));
printAge(person);
TimeUnit.DAYS.sleep(1);
printAge(person);
}
private static void printAge(Person person) {
System.out.println(person.name + " is " + person.getAge());
}
}
正确的输出是:
John Doe is 5
John Doe is 6
我们的单元测试可以像这样注入(inject)“现在”日期:
@Test
void testGetAge() {
Supplier<LocalDate> injectedNow = ()-> LocalDate.parse("2016-12-01");
Person person = new Person("John Doe", LocalDate.parse("2004-12-01"), injectedNow);
assertEquals(12, person.getAge());
}
关于java - 什么时候应该在 Java 8 中使用 Supplier?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40244571/