我有一个方法,大约有十行代码。我想创建更多的方法来做完全相同的事情,除了一个会改变一行代码的小计算。这是一个传递函数指针来替换这一行的完美应用程序,但是Java没有函数指针。我最好的选择是什么?
当前回答
谷歌Guava库正在变得非常流行,它有一个通用的Function和Predicate对象,它们已经在API的许多部分中使用了这些对象。
其他回答
如果有人试图传递一个函数,该函数使用一组参数来定义其行为,但使用另一组参数来执行,就像Scheme的:
(define (function scalar1 scalar2)
(lambda (x) (* x scalar1 scalar2)))
参见Java中参数定义行为的传递函数
你可能也会对Java 7中涉及闭包的工作感兴趣:
Java闭包的当前状态是什么?
http://gafter.blogspot.com/2006/08/closures-for-java.html http://tech.puredanger.com/java7/#closures
您需要创建一个接口,该接口提供您希望传递的函数。例如:
/**
* A simple interface to wrap up a function of one argument.
*
* @author rcreswick
*
*/
public interface Function1<S, T> {
/**
* Evaluates this function on it's arguments.
*
* @param a The first argument.
* @return The result.
*/
public S eval(T a);
}
然后,当你需要传递一个函数时,你可以实现这个接口:
List<Integer> result = CollectionUtilities.map(list,
new Function1<Integer, Integer>() {
@Override
public Integer eval(Integer a) {
return a * a;
}
});
最后,map函数使用Function1中传递的参数,如下所示:
public static <K,R,S,T> Map<K, R> zipWith(Function2<R,S,T> fn,
Map<K, S> m1, Map<K, T> m2, Map<K, R> results){
Set<K> keySet = new HashSet<K>();
keySet.addAll(m1.keySet());
keySet.addAll(m2.keySet());
results.clear();
for (K key : keySet) {
results.put(key, fn.eval(m1.get(key), m2.get(key)));
}
return results;
}
如果您不需要传递参数,您通常可以使用Runnable而不是自己的接口,或者您可以使用各种其他技术使参数计数不那么“固定”,但这通常是与类型安全的权衡。(或者你可以重写你的函数对象的构造函数,以这种方式传递参数。有很多方法,其中一些在特定情况下效果更好。)
匿名内部类
假设你想要传入一个带有String参数的函数,该参数返回一个整型。 首先,如果不能重用现有的接口,则必须定义一个接口,该接口的唯一成员是该函数。
interface StringFunction {
int func(String param);
}
接受指针的方法只接受StringFunction实例,如下所示:
public void takingMethod(StringFunction sf) {
int i = sf.func("my string");
// do whatever ...
}
并且会被这样称呼:
ref.takingMethod(new StringFunction() {
public int func(String param) {
// body
}
});
编辑:在Java 8中,你可以用lambda表达式调用它:
ref.takingMethod(param -> bodyExpression);
在Java 8之前,类似函数指针的功能最接近的替代品是匿名类。例如:
Collections.sort(list, new Comparator<CustomClass>(){
public int compare(CustomClass a, CustomClass b)
{
// Logic to compare objects of class CustomClass which returns int as per contract.
}
});
但现在在Java 8中,我们有一个非常简洁的替代方法,称为lambda表达式,它可以用作:
list.sort((a, b) -> { a.isBiggerThan(b) } );
其中isBiggerThan是CustomClass中的一个方法。我们也可以在这里使用方法引用:
list.sort(MyClass::isBiggerThan);
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap