Java Lambda捕获还是重新执行



制作一个功能接口

@FunctionalInterface
public RulesFact {
Object getPropertyValue(String propertyName);
}

方法内部的lambda实例。

public RulesFact rulesFactImpl(Object o) {
return propertyName->PropertyAccessorFactory.forBeanPropertyAccess(o).getPropertyValue(propertyName);
}

这个方法和上面的方法有区别吗?在上面的例子中,每次执行lambda时都会调用PropertyAccessorFactory.forBeanPropertyAccess方法吗?螺纹安全性有区别吗?

public RulesFact rulesFactImpl(Object o) {
BeanWrapper accessor = PropertyAccessorFactory.forBeanPropertyAccess(o);
return propertyName->accessor.getPropertyValue(propertyName);
}

关于上述反射实用程序的Javadocs:Package org.springframework.beans

调用RulesFact.getPropertyValue时执行lambda表达式。

这意味着每次调用RulesFact.getPropertyValue时,第一个版本都会调用PropertyAccessorFactory.forBeanPropertyAccess(o),如果访问器可以随时间变化,这是很好的。

第二个版本在调用rulesFactImpl时调用PropertyAccessorFactory.forBeanPropertyAccess(o),并缓存该值,这对性能有利,但如果访问器可以随时间变化,则不好。

FYI:第二个版本可以使用方法参考编写:

public RulesFact rulesFactImpl(Object o) {
BeanWrapper accessor = PropertyAccessorFactory.forBeanPropertyAccess(o);
return accessor::getPropertyValue;
}

稍微有点,但可能不是以你关心的方式,假设这些API写得相当好。

public RulesFact rulesFactImpl(Object o) {
return propertyName->PropertyAccessorFactory.forBeanPropertyAccess(o).getPropertyValue(propertyName);
}

这会返回一个RulesFact,当被调用时,它会调用forBeanPropertyAccess,然后对其执行任何操作。如果您多次调用它,它每次都会调用forBeanPropertyAccess

public RulesFact rulesFactImpl(Object o) {
BeanWrapper accessor = PropertyAccessorFactory.forBeanPropertyAccess(o);
return propertyName->accessor.getPropertyValue(propertyName);
}

这会调用forBeanPropertyAccess一次,并围绕其值进行闭包。您可以将这个闭包看作是一个实例变量。从某种意义上说,我们正在制作RulesFact的一个子类,它有一个名为accessor的实例变量,其值在构建时只计算一次。如果我们多次调用这个lambda,forBeanPropertyAccess将永远不会再被调用;它只会多次使用原始值。

它或多或少是相同的,但在功能上并不相同。假设PropertyAccessorFactory.forBeanPropertyAccess(o)抛出异常。

在第一种情况下,rulesFactImpl(...)永远不会抛出。如果从未调用过RulesFact.getPropertyValue,则不会有任何异常。

在第二种情况下,rulesFactImpl(...)总是抛出。

最新更新