我有一个方法,大约有十行代码。我想创建更多的方法来做完全相同的事情,除了一个会改变一行代码的小计算。这是一个传递函数指针来替换这一行的完美应用程序,但是Java没有函数指针。我最好的选择是什么?
当前回答
在没有函数数组接口的情况下做同样的事情:
class NameFuncPair
{
public String name; // name each func
void f(String x) {} // stub gets overridden
public NameFuncPair(String myName) { this.name = myName; }
}
public class ArrayOfFunctions
{
public static void main(String[] args)
{
final A a = new A();
final B b = new B();
NameFuncPair[] fArray = new NameFuncPair[]
{
new NameFuncPair("A") { @Override void f(String x) { a.g(x); } },
new NameFuncPair("B") { @Override void f(String x) { b.h(x); } },
};
// Go through the whole func list and run the func named "B"
for (NameFuncPair fInstance : fArray)
{
if (fInstance.name.equals("B"))
{
fInstance.f(fInstance.name + "(some args)");
}
}
}
}
class A { void g(String args) { System.out.println(args); } }
class B { void h(String args) { System.out.println(args); } }
其他回答
如果有人试图传递一个函数,该函数使用一组参数来定义其行为,但使用另一组参数来执行,就像Scheme的:
(define (function scalar1 scalar2)
(lambda (x) (* x scalar1 scalar2)))
参见Java中参数定义行为的传递函数
对于每个“函数指针”,我会创建一个小的函子类来实现你的计算。 定义一个所有类都将实现的接口,并将这些对象的实例传递到更大的函数中。这是“命令模式”和“战略模式”的结合。
@sblundy的例子很好。
从Java8开始,您可以使用lambdas,它在官方SE 8 API中也有库。
用法: 您只需要使用带有一个抽象方法的接口。 创建一个实例(你可能想使用java SE 8已经提供的实例),如下所示:
Function<InputType, OutputType> functionname = (inputvariablename) {
...
return outputinstance;
}
有关更多信息,请查看文档:https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
在用Java编程时,我真正怀念的一件事是函数回调。在递归处理层次结构中,需要不断地呈现这些元素,您希望为每个元素执行特定的操作。比如遍历目录树,或者处理数据结构。我内心的极简主义者讨厌为每个特定的情况定义接口和实现。
有一天我发现自己在想为什么不呢?我们有方法指针——method对象。通过优化JIT编译器,反射调用实际上不再带来巨大的性能损失。此外,除了将文件从一个位置复制到另一个位置之外,反射方法调用的成本变得微不足道。
随着我对它的深入思考,我意识到OOP范式中的回调需要将对象和方法绑定在一起——进入回调对象。
请查看我的基于反射的Java回调解决方案。免费供任何用途。
在没有函数数组接口的情况下做同样的事情:
class NameFuncPair
{
public String name; // name each func
void f(String x) {} // stub gets overridden
public NameFuncPair(String myName) { this.name = myName; }
}
public class ArrayOfFunctions
{
public static void main(String[] args)
{
final A a = new A();
final B b = new B();
NameFuncPair[] fArray = new NameFuncPair[]
{
new NameFuncPair("A") { @Override void f(String x) { a.g(x); } },
new NameFuncPair("B") { @Override void f(String x) { b.h(x); } },
};
// Go through the whole func list and run the func named "B"
for (NameFuncPair fInstance : fArray)
{
if (fInstance.name.equals("B"))
{
fInstance.f(fInstance.name + "(some args)");
}
}
}
}
class A { void g(String args) { System.out.println(args); } }
class B { void h(String args) { System.out.println(args); } }
推荐文章
- 在流中使用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