从 JAVA 中的用户输入调用方法
Calling a method from user input in JAVA
我正在寻找一种方法来调用我的 class 中的任何给定方法,而不必执行整个 try-catch
语句。
示例:
public void Worker(String handle) throws Exception
{
if(PROTOCOL.contains(handle))
{
System.out.println("good");
Worker.handle;
}
else {
throw new Exception("Don't understand <" + handle + ">");
}
}
PROTOCOL
是允许的命令列表。
我知道我可以说 if(input = ....){do....}
但我希望能够做到以上几点;使用输入值调用我的 class。
这可能吗?
如果您不想使用 try-catch(自己处理异常),则在调用方法中声明这些异常,紧跟在 throws 关键字之后。
https://docs.oracle.com/javase/tutorial/essential/exceptions/declaring.html
基本上您是将异常处理委托给方法的调用者。
根据您的命令看起来像什么,您可以使用 Map<String, Command>
然后像这样使用它:
Map<String, Command> PROTOCOL = ... //you build that map somehow
Command c = PROTOCOL.get(handle);
if( c != null ) {
System.out.println("good");
c.execute();
} else {
throw new Exception("Don't understand <" + handle + ">");
}
Command
可以是 class 或函数接口:
interface Command {
void execute();
}
用作class接口
class MyCommand implements Command {
//this can have private data
void execute() {
//do whatever is needed
}
}
PROTOCOL.put("mycommand", new MyCommand(/*you could pass parameters here*/));
优点:
- 接口可以有不止一种方法,例如它也可以有一个
String getName()
。
- 命令可以有参数,例如您可以提供一个实现并使用不同的名称绑定到具有不同参数的同一命令(例如 "increment" 和 "decrement" 可以绑定到
AddCommand(1)
和 AddCommand(-1)
)。
- 您可以使用一些依赖倒置机制(例如通过 CDI)让命令将自己注册到
PROTOCOL
。这样你甚至可以通过一些插件机制添加命令。
- 使用 classes 的接口对其他人来说可能更容易掌握。
- 更容易构建更大的命令,因为您可以轻松地将 classes 提取到单独的文件中。
用作函数接口(例如通过 lambda)
PROTOCOL.put("mycommand", () -> {
//do whatever is needed
});
优点:
- 不需要 classes 可以使短命令更简洁。
这是一个简单的工作示例,展示了您可以使用 reflection 执行的一些操作。
注意:我决定将可用方法存储在列表中,但这可以很容易地修改为使用预定义的字符串列表。我还从 worker 方法中抛出了一个未经检查的 IllegalArgumentException。
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Worker {
public void method1() {
System.out.println("method1 called");
}
public void method2() {
System.out.println("method2 called");
}
public void worker(String handle) throws IllegalArgumentException {
Class<? extends Worker> clazz = this.getClass();
List<Method> methods = Arrays.asList(clazz.getMethods());
if (methods.stream().map(m -> m.getName()).collect(Collectors.toList()).contains(handle)) {
try {
Method method = clazz.getDeclaredMethod(handle);
method.invoke(this);
} catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
e.printStackTrace();
}
} else {
throw new IllegalArgumentException("Don't understand <" + handle + ">");
}
}
public static void main(String[] args) {
new Worker().worker("method1");
new Worker().worker("method2");
new Worker().worker("method3");
}
}
我正在寻找一种方法来调用我的 class 中的任何给定方法,而不必执行整个 try-catch
语句。
示例:
public void Worker(String handle) throws Exception
{
if(PROTOCOL.contains(handle))
{
System.out.println("good");
Worker.handle;
}
else {
throw new Exception("Don't understand <" + handle + ">");
}
}
PROTOCOL
是允许的命令列表。
我知道我可以说 if(input = ....){do....}
但我希望能够做到以上几点;使用输入值调用我的 class。
这可能吗?
如果您不想使用 try-catch(自己处理异常),则在调用方法中声明这些异常,紧跟在 throws 关键字之后。
https://docs.oracle.com/javase/tutorial/essential/exceptions/declaring.html
基本上您是将异常处理委托给方法的调用者。
根据您的命令看起来像什么,您可以使用 Map<String, Command>
然后像这样使用它:
Map<String, Command> PROTOCOL = ... //you build that map somehow
Command c = PROTOCOL.get(handle);
if( c != null ) {
System.out.println("good");
c.execute();
} else {
throw new Exception("Don't understand <" + handle + ">");
}
Command
可以是 class 或函数接口:
interface Command {
void execute();
}
用作class接口
class MyCommand implements Command {
//this can have private data
void execute() {
//do whatever is needed
}
}
PROTOCOL.put("mycommand", new MyCommand(/*you could pass parameters here*/));
优点:
- 接口可以有不止一种方法,例如它也可以有一个
String getName()
。 - 命令可以有参数,例如您可以提供一个实现并使用不同的名称绑定到具有不同参数的同一命令(例如 "increment" 和 "decrement" 可以绑定到
AddCommand(1)
和AddCommand(-1)
)。 - 您可以使用一些依赖倒置机制(例如通过 CDI)让命令将自己注册到
PROTOCOL
。这样你甚至可以通过一些插件机制添加命令。 - 使用 classes 的接口对其他人来说可能更容易掌握。
- 更容易构建更大的命令,因为您可以轻松地将 classes 提取到单独的文件中。
用作函数接口(例如通过 lambda)
PROTOCOL.put("mycommand", () -> {
//do whatever is needed
});
优点:
- 不需要 classes 可以使短命令更简洁。
这是一个简单的工作示例,展示了您可以使用 reflection 执行的一些操作。
注意:我决定将可用方法存储在列表中,但这可以很容易地修改为使用预定义的字符串列表。我还从 worker 方法中抛出了一个未经检查的 IllegalArgumentException。
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Worker {
public void method1() {
System.out.println("method1 called");
}
public void method2() {
System.out.println("method2 called");
}
public void worker(String handle) throws IllegalArgumentException {
Class<? extends Worker> clazz = this.getClass();
List<Method> methods = Arrays.asList(clazz.getMethods());
if (methods.stream().map(m -> m.getName()).collect(Collectors.toList()).contains(handle)) {
try {
Method method = clazz.getDeclaredMethod(handle);
method.invoke(this);
} catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
e.printStackTrace();
}
} else {
throw new IllegalArgumentException("Don't understand <" + handle + ">");
}
}
public static void main(String[] args) {
new Worker().worker("method1");
new Worker().worker("method2");
new Worker().worker("method3");
}
}