Java Lambda 捕获还是重新执行?
Java Lambda capture or re execute?
制作函数式界面
@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);
}
关于上述反射实用程序的 Javadoc:Package org.springframework.beans
假设这些 API 编写得相当好,有一点,但可能不是您关心的方式。
public RulesFact rulesFactImpl(Object o) {
return propertyName->PropertyAccessorFactory.forBeanPropertyAccess(o).getPropertyValue(propertyName);
}
This returns a RulesFact
调用时调用 forBeanPropertyAccess
然后对其进行任何操作。如果多次调用它,它每次都会调用 forBeanPropertyAccess
。
public RulesFact rulesFactImpl(Object o) {
BeanWrapper accessor = PropertyAccessorFactory.forBeanPropertyAccess(o);
return propertyName->accessor.getPropertyValue(propertyName);
}
这会调用 forBeanPropertyAccess
一次并围绕其值进行关闭。你可以把这个闭包想象成一个实例变量。从某种意义上说,我们正在创建 RulesFact
的子类,它有一个名为 accessor
的实例变量,其值仅在构造时计算一次。如果我们多次调用这个 lambda,forBeanPropertyAccess
将永远不会被再次调用;它只会多次使用原始值。
调用RulesFact.getPropertyValue
时执行lambda表达式。
这意味着第一个版本每次调用RulesFact.getPropertyValue
时都会调用PropertyAccessorFactory.forBeanPropertyAccess(o)
,如果访问器可以随时间变化,这很好。
第二个版本在调用 rulesFactImpl
时调用 PropertyAccessorFactory.forBeanPropertyAccess(o)
,并缓存值,这对性能有好处,但如果访问者可以随时间变化则不好。
仅供参考:第二个版本可以使用方法参考:
public RulesFact rulesFactImpl(Object o) {
BeanWrapper accessor = PropertyAccessorFactory.forBeanPropertyAccess(o);
return accessor::getPropertyValue;
}
它或多或少相同,但在功能上并不相同。假设 PropertyAccessorFactory.forBeanPropertyAccess(o)
抛出异常。
在第一种情况下,rulesFactImpl(...)
永远不会抛出。只要 RulesFact.getPropertyValue
从未被调用过,就不会有例外。
在第二种情况下,rulesFactImpl(...)
总是会抛出。
制作函数式界面
@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);
}
关于上述反射实用程序的 Javadoc:Package org.springframework.beans
假设这些 API 编写得相当好,有一点,但可能不是您关心的方式。
public RulesFact rulesFactImpl(Object o) {
return propertyName->PropertyAccessorFactory.forBeanPropertyAccess(o).getPropertyValue(propertyName);
}
This returns a RulesFact
调用时调用 forBeanPropertyAccess
然后对其进行任何操作。如果多次调用它,它每次都会调用 forBeanPropertyAccess
。
public RulesFact rulesFactImpl(Object o) {
BeanWrapper accessor = PropertyAccessorFactory.forBeanPropertyAccess(o);
return propertyName->accessor.getPropertyValue(propertyName);
}
这会调用 forBeanPropertyAccess
一次并围绕其值进行关闭。你可以把这个闭包想象成一个实例变量。从某种意义上说,我们正在创建 RulesFact
的子类,它有一个名为 accessor
的实例变量,其值仅在构造时计算一次。如果我们多次调用这个 lambda,forBeanPropertyAccess
将永远不会被再次调用;它只会多次使用原始值。
调用RulesFact.getPropertyValue
时执行lambda表达式。
这意味着第一个版本每次调用RulesFact.getPropertyValue
时都会调用PropertyAccessorFactory.forBeanPropertyAccess(o)
,如果访问器可以随时间变化,这很好。
第二个版本在调用 rulesFactImpl
时调用 PropertyAccessorFactory.forBeanPropertyAccess(o)
,并缓存值,这对性能有好处,但如果访问者可以随时间变化则不好。
仅供参考:第二个版本可以使用方法参考:
public RulesFact rulesFactImpl(Object o) {
BeanWrapper accessor = PropertyAccessorFactory.forBeanPropertyAccess(o);
return accessor::getPropertyValue;
}
它或多或少相同,但在功能上并不相同。假设 PropertyAccessorFactory.forBeanPropertyAccess(o)
抛出异常。
在第一种情况下,rulesFactImpl(...)
永远不会抛出。只要 RulesFact.getPropertyValue
从未被调用过,就不会有例外。
在第二种情况下,rulesFactImpl(...)
总是会抛出。