Reputation: 11551
Make a functional interface
@FunctionalInterface
public RulesFact {
Object getPropertyValue(String propertyName);
}
An instance a lambda inside a method.
public RulesFact rulesFactImpl(Object o) {
return propertyName->PropertyAccessorFactory.forBeanPropertyAccess(o).getPropertyValue(propertyName);
}
Is there a difference between this method and the above one? In the above one, does the PropertyAccessorFactory.forBeanPropertyAccess
method get called each time the lambda is executed? Is there a difference in thread safety?
public RulesFact rulesFactImpl(Object o) {
BeanWrapper accessor = PropertyAccessorFactory.forBeanPropertyAccess(o);
return propertyName->accessor.getPropertyValue(propertyName);
}
Javadocs on above reflection utils: Package org.springframework.beans
Upvotes: 2
Views: 111
Reputation: 44210
It's more or less the same but it's not functionally identical. Suppose PropertyAccessorFactory.forBeanPropertyAccess(o)
throws an exception.
In the first case, rulesFactImpl(...)
would never throw. Provided RulesFact.getPropertyValue
was never called, there would be no exceptions.
In the second case,rulesFactImpl(...)
would always throw.
Upvotes: 0
Reputation: 159135
The lambda expression is executed when RulesFact.getPropertyValue
is called.
Which means that the first version calls PropertyAccessorFactory.forBeanPropertyAccess(o)
every time RulesFact.getPropertyValue
is called, which is good if the accessor can change over time.
The second version calls PropertyAccessorFactory.forBeanPropertyAccess(o)
when rulesFactImpl
is called, and caches the value, which is good for performance, but bad if the accessor can change over time.
FYI: The second version can be written using method reference:
public RulesFact rulesFactImpl(Object o) {
BeanWrapper accessor = PropertyAccessorFactory.forBeanPropertyAccess(o);
return accessor::getPropertyValue;
}
Upvotes: 2
Reputation: 70307
Slightly, but probably not in a way you care about, assuming these APIs are reasonably well-written.
public RulesFact rulesFactImpl(Object o) {
return propertyName->PropertyAccessorFactory.forBeanPropertyAccess(o).getPropertyValue(propertyName);
}
This returns a RulesFact
that, when called, invokes forBeanPropertyAccess
and then does whatever work on it. If you call it multiple times, it calls forBeanPropertyAccess
each time.
public RulesFact rulesFactImpl(Object o) {
BeanWrapper accessor = PropertyAccessorFactory.forBeanPropertyAccess(o);
return propertyName->accessor.getPropertyValue(propertyName);
}
This calls forBeanPropertyAccess
once and makes a closure around its value. You can think of this closure as being like an instance variable. We're, in some sense, making a subclass of RulesFact
which has an instance variable called accessor
whose value is computed at construction time only once. If we call this lambda several times, forBeanPropertyAccess
will never get called again; it'll just use the original value several times.
Upvotes: 1