在Java8之后,当定义的接口中只有一个函数,可以用作函数指针。
比如,定义一个输入参数为String返回String的函数。
public interface TestFuncPoint {
String run(String str);
}
那么如何使用呢?
比如,我们需要定义一个函数,接受一个函数指针,并使用这个函数指针。
public interface TestFuncPoint {
String run(String str);
}
// 定义一个类,在runFunc中使用这个函数指针
public class Demo {
void runFunc(TestFuncPoint funcPoint) {
System.out.println(funcPoint.run("Ted"));
}
}
public class Main {
public static void main(String[] args) {
Demo d = new Demo();
// 将函数的具体实现,传入runFunc中
d.runFunc(Main::funcImpl);
}
// 定义具体函数
public static String funcImpl(String str) {
return "hi " + str;
}
}
这样操作就可以非常灵活的,将之前只能通过反射实现的业务逻辑,做的更高效、清楚。
比如有这样一个业务需求。根据用户选择的功能,运行某一函数。入参是一个String类型的功能名称(不一定是函数名)。
如果按照没有函数指针的话,我们需要反射实现。
public class Demo {
Map<String, String> funcMap = new HashMap<>();
public Demo() {
init();
}
void init() {
funcMap.put("叫我爸爸", "callBaBa");
funcMap.put("叫我妈妈", "callMaMa");
funcMap.put("叫我爷爷", "callYeYe");
}
public void call(String funcName) {
// 通过反射获取具体实现函数
String methodName = funcMap.get(funcName);
if (methodName != null) {
try {
Method method = Demo.class.getMethod(methodName);
method.invoke(this);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
public void callBaBa() {
System.out.println("爸爸!");
}
public void callMaMa() {
System.out.println("妈妈!");
}
public void callYeYe() {
System.out.println("爷爷!");
}
}
public class Main {
public static void main(String[] args) {
Demo demo = new Demo();
// 模拟用户输入了"叫我爸爸"
demo.call("叫我爸爸");
}
}
如果有函数指针的话,就可以使逻辑更加清楚,执行效率更快。
public interface TestFuncPoint {
void run();
}
public class Demo {
Map<String, TestFuncPoint> funcMap = new HashMap<>();
public Demo() {
init();
}
void init() {
// 这里的值是指向具体函数的指针
funcMap.put("叫我爸爸", this::callBaBa);
funcMap.put("叫我妈妈", this::callMaMa);
funcMap.put("叫我爷爷", this::callYeYe);
}
public void call(String funcName) {
TestFuncPoint method = funcMap.get(funcName);
if (method != null) {
method.run();
}
}
public void callBaBa() {
System.out.println("爸爸!");
}
public void callMaMa() {
System.out.println("妈妈!");
}
public void callYeYe() {
System.out.println("爷爷!");
}
}
public class Main {
public static void main(String[] args) {
Demo demo = new Demo();
demo.call("叫我爸爸");
}
}
同样的,也可以实现事件效果。
比如,按下一个按钮之后,打印按下了按钮
public interface Event {
void run();
}
public class Demo {
private Event event;
public void submitEvent(Event event) {
this.event = event;
}
void raiseEvent() {
this.event.run();
}
}
public class Main {
public static void main(String[] args) {
Demo d = new Demo();
// 订阅事件
d.submitEvent(Main::buttonPressed);
// 模拟事件发生
d.raiseEvent();
}
public static void buttonPressed() {
System.out.println("按下了按钮");
}
}