Java中能否将Mutator方法作为参数传入其他方法?游戏开发场景求助
解决方案:用函数式接口实现通用的输入校验与属性设置
刚接触Java遇到这种问题很正常,你想把mutator方法作为参数传递的思路是对的,但Java里不能直接传void类型的方法——因为方法参数需要是一个可以引用的对象或函数实例,而void方法没有返回值,也不是一个可传递的"函数对象"。不过Java 8之后引入的函数式接口正好能解决这个问题,而且非常适合你这种通用校验的场景。
我们可以用Java标准库自带的两个函数式接口来实现需求:
Supplier<String>:用来获取当前属性的值(对应你的getter方法),它的get()方法会返回一个String。Consumer<String>:用来设置新的属性值(对应你的setter方法),它的accept(String)方法会接收一个字符串并执行设置逻辑。
重构通用校验方法
把你原来的confirmEntry方法修改成接收这两个接口作为参数,这样就能适配任何需要校验和设置的字符串属性(名称、年龄描述等):
import java.util.Scanner; import java.util.function.Consumer; import java.util.function.Supplier; public void confirmEntry(String prompt, String[] options, Supplier<String> valueGetter, Consumer<String> valueSetter) throws InterruptedException { boolean isConfirmed = false; Scanner in = new Scanner(System.in); // 如果类里已有全局Scanner可直接使用 String input; while (!isConfirmed) { // 展示当前选择并询问确认 System.out.println("You chose: " + valueGetter.get()); Thread.sleep(2000); System.out.print("Is this correct? "); // 格式化输出选项 for (int i = 0; i < options.length - 1; i++) { System.out.print(options[i] + ", "); } System.out.println("or " + options[options.length - 1] + ": "); input = in.nextLine().trim().toLowerCase(); // 校验输入是否在合法选项内 boolean validInput = false; for (String option : options) { if (input.equals(option)) { validInput = true; break; } } if (!validInput) { // 非法输入提示 Thread.sleep(2000); System.out.print("Invalid input! You must enter "); for (int i = 0; i < options.length - 1; i++) { System.out.print("\"" + options[i] + "\", "); } System.out.println("or \"" + options[options.length - 1] + "\" to continue."); continue; } // 处理合法输入的确认逻辑 if (input.equals("yes")) { isConfirmed = true; System.out.println("Confirmed!"); } else { // 用户选择重新输入,更新属性值 Thread.sleep(2000); System.out.print(prompt + " "); input = in.nextLine().trim(); valueSetter.accept(input); // 调用setter设置新值 } } }
在角色创建中调用通用方法
现在你可以在characterCreation里用Lambda表达式传入getter和setter,代码会简洁很多,而且可以复用这个方法处理其他属性(比如年龄、职业等):
public void characterCreation() throws Exception { Player character = new Player(); Scanner in = new Scanner(System.in); String[] yesNo = {"yes", "no"}; // 初始游戏介绍 System.out.println("Welcome to Stranded!"); Thread.sleep(2000); System.out.println("Tell us a little about yourself!"); Thread.sleep(2000); // 设置角色名称 System.out.print("Enter your character's name: "); String nameInput = in.nextLine().trim(); character.setName(nameInput); // 调用通用校验方法,传入getName()作为Supplier,setName()作为Consumer confirmEntry("Enter your character's name again:", yesNo, () -> character.getName(), // Lambda:获取当前角色名称 newName -> character.setName(newName) // Lambda:设置新的角色名称 ); // 复用方法处理其他属性示例(比如年龄描述) /* System.out.print("Enter your character's age description (e.g., 'young', 'middle-aged'): "); String ageInput = in.nextLine().trim(); character.setAgeDescription(ageInput); confirmEntry("Enter your character's age description again:", yesNo, () -> character.getAgeDescription(), newAge -> character.setAgeDescription(newAge) ); */ }
关键概念解释
- Lambda表达式:
() -> character.getName()相当于一个匿名的Supplier,调用它的get()方法就会返回角色的名称;newName -> character.setName(newName)是一个匿名的Consumer,调用accept(newName)就会把新名称设置给角色。 - 通用性:这个
confirmEntry方法现在可以处理任何字符串类型的属性,不管是名称、年龄描述还是职业,只要传入对应的getter和setter Lambda就行,完全消除了重复代码。
额外优化建议
- 把
yesNo数组提取成类常量,避免重复创建:private static final String[] YES_NO_OPTIONS = {"yes", "no"}; - 可以把初始输入的逻辑也封装到
confirmEntry里,让调用更简洁(比如添加一个参数控制是否需要初始输入)。 - 处理输入时记得用
trim()和toLowerCase(),避免用户输入空格或大小写不一致导致的错误。
内容的提问来源于stack exchange,提问作者C.StG
相关产品推荐
相关产品推荐

