这可能是常见且琐碎的事情,但我似乎很难找到具体答案。在C#中,有一个委托的概念,它与C ++中的函数指针紧密相关。Java中是否有类似的功能?鉴于缺少指针,最好的方法是什么?需要明确的是,我们在这里谈论头等舱。
这可能是常见且琐碎的事情,但我似乎很难找到具体答案。在C#中,有一个委托的概念,它与C ++中的函数指针紧密相关。Java中是否有类似的功能?鉴于缺少指针,最好的方法是什么?需要明确的是,我们在这里谈论头等舱。
Answers:
类似函数指针的功能的Java习惯用法是实现接口的匿名类,例如
Collections.sort(list, new Comparator<MyClass>(){
public int compare(MyClass a, MyClass b)
{
// compare objects
}
});
更新:以上是Java 8之前的Java版本中必需的。现在,我们有更好的替代方法,即lambda:
list.sort((a, b) -> a.isGreaterThan(b));
和方法参考:
list.sort(MyClass::isGreaterThan);
std::bind
将参数绑定到函数并返回可调用对象的。我不能防守C对这些理由,但C ++真的是比Java为了这个美好的。
您可以用接口替换函数指针。假设您要遍历一个集合并对每个元素执行某项操作。
public interface IFunction {
public void execute(Object o);
}
这是我们可以传递给诸如CollectionUtils2.doFunc(Collection c,IFunction f)的接口。
public static void doFunc(Collection c, IFunction f) {
for (Object o : c) {
f.execute(o);
}
}
例如,我们有一个数字集合,您想为每个元素加1。
CollectionUtils2.doFunc(List numbers, new IFunction() {
public void execute(Object o) {
Integer anInt = (Integer) o;
anInt++;
}
});
您可以使用反射来做到这一点。
将对象和方法名称(作为字符串)作为参数传递,然后调用该方法。例如:
Object methodCaller(Object theObject, String methodName) {
return theObject.getClass().getMethod(methodName).invoke(theObject);
// Catch the exceptions
}
然后按以下方式使用它:
String theDescription = methodCaller(object1, "toString");
Class theClass = methodCaller(object2, "getClass");
当然,请检查所有异常并添加所需的强制类型转换。
不,函数不是Java中的一流对象。您可以通过实现处理程序类来做同样的事情-这就是在Swing等中实现回调的方式。
但是,在Java的未来版本中有闭包的建议(您正在谈论的正式名称)-Javaworld有一篇有趣的文章。
Java8引入了lambda和方法引用。因此,如果您的函数与功能接口匹配(可以创建自己的接口),则在这种情况下可以使用方法引用。
Java提供了一组通用的功能接口。而您可以执行以下操作:
public class Test {
public void test1(Integer i) {}
public void test2(Integer i) {}
public void consumer(Consumer<Integer> a) {
a.accept(10);
}
public void provideConsumer() {
consumer(this::test1); // method reference
consumer(x -> test2(x)); // lambda
}
}
alias
:例如 public List<T> collect(T t) = Collections::collect
Java中没有这样的东西。您将需要将函数包装到某个对象中,并将引用传递给该对象,以便将该引用传递给该对象上的方法。
从句法上讲,可以通过使用就地定义的匿名类或定义为该类的成员变量的匿名类在一定程度上缓解这种情况。
例:
class MyComponent extends JPanel {
private JButton button;
public MyComponent() {
button = new JButton("click me");
button.addActionListener(buttonAction);
add(button);
}
private ActionListener buttonAction = new ActionListener() {
public void actionPerformed(ActionEvent e) {
// handle the event...
// note how the handler instance can access
// members of the surrounding class
button.setText("you clicked me");
}
}
}
我已经使用反射在Java中实现了回调/委托支持。详细信息和工作源可在我的网站上找到。
这个怎么运作
我们有一个名为Callback的主体类,以及一个名为WithParms的嵌套类。需要回调的API将把Callback对象作为参数,并在必要时创建一个Callback.WithParms作为方法变量。由于此对象的许多应用程序都是递归的,因此可以很干净地工作。
由于性能仍然是我的重中之重,因此我不需要创建一个一次性对象数组来保存每次调用的参数-毕竟,在大型数据结构中,可能有成千上万的元素,并且在消息处理中在这种情况下,我们最终可能每秒处理数千个数据结构。
为了确保线程安全,参数数组必须在API方法的每次调用中唯一存在,并且为了提高效率,应在回调的每次调用中使用相同的参数数组。我需要第二个对象,该对象创建起来很便宜,以便将回调与参数数组绑定以进行调用。但是,在某些情况下,由于其他原因,调用者将已经具有参数数组。由于这两个原因,参数数组不属于Callback对象。同样,调用的选择(将参数作为数组或作为单个对象传递)也使用回调在API手中,从而使它能够使用最适合其内部工作方式的任何调用。
然后,WithParms嵌套类是可选的,有两个作用,它包含回调调用所需的参数对象数组,并提供10个重载invoke()方法(具有1到10个参数),这些方法将加载参数数组,然后调用回调目标。
检查闭包如何在lambdaj库中实现。实际上,它们的行为与C#委托非常相似:
相对于这里的大多数人,我是Java的新手,但是由于我没有看到类似的建议,因此我有另一种建议。我不确定这是否是一个好的做法,或者甚至以前没有建议过,但我只是没有得到。我喜欢它,因为我认为它具有自我描述性。
/*Just to merge functions in a common name*/
public class CustomFunction{
public CustomFunction(){}
}
/*Actual functions*/
public class Function1 extends CustomFunction{
public Function1(){}
public void execute(){...something here...}
}
public class Function2 extends CustomFunction{
public Function2(){}
public void execute(){...something here...}
}
.....
/*in Main class*/
CustomFunction functionpointer = null;
然后根据应用程序分配
functionpointer = new Function1();
functionpointer = new Function2();
等等
并致电
functionpointer.execute();