Java控制台菜单如何支持任意参数类型的回调方法?
解决方案:用Lambda表达式绑定任意方法与参数
要让ConsoleMenu支持任意方法作为回调,核心思路是将方法调用与所需参数封装成一个无参的可执行任务,无需关心原方法的参数类型和数量。具体实现步骤如下:
1. 重新定义ConsoleMenuItem类
让它存储菜单描述和一个可执行的任务,无需直接处理方法参数:
public class ConsoleMenuItem { private final String description; private final Runnable action; public ConsoleMenuItem(String description, Runnable action) { this.description = description; this.action = action; } public String getDescription() { return description; } public void execute() { action.run(); } }
2. 修改ConsoleMenu的addMenuItem方法
不需要专门处理参数,直接接收描述和一个Runnable实例。调用方可以通过Lambda表达式将任意方法与参数绑定成Runnable:
import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class ConsoleMenu { private final List<ConsoleMenuItem> menuItems = new ArrayList<>(); private final Scanner scanner = new Scanner(System.in); // 通用添加菜单方法,支持任意方法+参数组合 public void addMenuItem(String description, Runnable action) { menuItems.add(new ConsoleMenuItem(description, action)); } public void displayMenu() { System.out.println("=== 控制台菜单 ==="); for (int i = 0; i < menuItems.size(); i++) { System.out.printf("%d. %s%n", i + 1, menuItems.get(i).getDescription()); } System.out.print("请输入选择编号:"); } public void handleUserChoice() { displayMenu(); int choice = scanner.nextInt(); if (choice >= 1 && choice <= menuItems.size()) { // 直接执行对应菜单的回调任务 menuItems.get(choice - 1).execute(); } else { System.out.println("无效选择,请重新输入!"); handleUserChoice(); } } // 测试示例 public static void main(String[] args) { ConsoleMenu menu = new ConsoleMenu(); // 绑定无参方法 menu.addMenuItem("显示欢迎语", () -> printWelcome()); // 绑定带不同类型参数的方法 menu.addMenuItem("显示用户信息", () -> printUserInfo("YoavKlein", 30)); // 绑定带多个参数的业务方法 menu.addMenuItem("计算两数乘积", () -> calculateProduct(15, 25)); menu.handleUserChoice(); } // 示例业务方法:无参 private static void printWelcome() { System.out.println("欢迎使用控制台菜单系统!"); } // 示例业务方法:多类型参数 private static void printUserInfo(String username, int age) { System.out.printf("用户名:%s,年龄:%d%n", username, age); } // 示例业务方法:数值参数 private static void calculateProduct(int a, int b) { System.out.printf("%d × %d = %d%n", a, b, a * b); } }
3. 扩展支持带返回值的回调
如果需要回调方法返回结果,可以自定义函数式接口替代Runnable:
@FunctionalInterface public interface MenuCommand<T> { T execute(); }
然后修改ConsoleMenuItem:
public class ConsoleMenuItem<T> { private final String description; private final MenuCommand<T> command; public ConsoleMenuItem(String description, MenuCommand<T> command) { this.description = description; this.command = command; } public String getDescription() { return description; } public T execute() { return command.execute(); } }
调用时可以接收返回值:
menu.addMenuItem("获取当前时间", () -> LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); // 执行时获取结果 String time = menuItems.get(0).execute(); System.out.println("当前时间:" + time);
核心优势
- 类型安全:编译阶段就能检查方法参数是否匹配,避免反射带来的运行时错误
- 灵活性高:支持任意数量、任意类型参数的方法,无需修改
ConsoleMenu核心逻辑 - 代码简洁:Lambda表达式直接绑定方法与参数,可读性强
内容的提问来源于stack exchange,提问作者YoavKlein
相关产品推荐
相关产品推荐

