[英]How can I dynamically call methods in Java
我对Java很陌生,所以请彻底。 我正在创建一个程序,该程序使用方法库来搜索具有各种正则表达式的文本文件。 检查列表可能会根据文本文件的类型(文本文件是网络设备配置文件)的类型而变化。 有些检查适用于某些设备,而不适用于其他设备。 每个检查都是通过调用其方法来执行的。 我遇到的问题是,因为所有检查都不适用,并且我不知道哪种检查要等到运行时才适用。 因此,当用户选择要检查的设备时,我需要能够使用运行时创建的列表中的字符串调用方法。 例如:我认为我需要能够使用列表的String Contents来确定确定执行哪些检查的方法
String[] checklist = {"check100", "check101", "check105"}; // list of checks to perform
String chk = checklist[0]; // String containing a check to be performed (Function Call)
chk(config); // Where it all goes wrong... I want to make a call to the check100 method using the value of chk
...
public void check100 (String[] configFile){ // performs the configFile check100
...
...
}
public void check101 (String[] configFile){ // performs the configFile check101
...
...
}
public void check103 (String[] configFile){ // check not applicable to this device
...
...
} `
我试着看反射,但似乎无法弄清楚。 如果有更好的方法可以不使用反射功能,请告诉我。
解决方案1:
这可以使用Java的Reflection API来完成
public static void checkAll( String[] checks, String[] configFile ) {
Class< ? > cl = Check.class; // Class object where all check methods are.
for( String check : checks ) {
Method m = cl.getMethod( check );
m.invoke( null, configFile );
}
}
在考虑使用此方法之前,应阅读一些警告。 我没有添加任何错误处理,并且此代码无法编译。 反射API可能引发许多我未介绍的潜在异常。 您应该阅读使用的每种方法,并考虑如何处理每个潜在的错误。
另一个警告是反射很慢,它比静态地直接调用每种方法要慢得多。 如果您担心性能或类型安全,请考虑使用解决方案2。
解决方案2:
更好的解决方案是对每个检查使用通用接口。
public interface Check {
void check( String[] configFile );
}
然后,您创建了一堆实现该接口的类,并将它们添加到一个Map中,您可以在其中使用名称或ID查找要运行的每个检查。 这比基于反射的方法快得多,并且类型安全。
例:
public class Check1 implements Check {
public void check( String[] configFile ) {
// Do check stuff
}
}
public class Check2 implements Check {
public void check( String[] configFile ) {
// More check stuff
}
}
public class ConfigCheck {
public static Map< String, Check > nameToCheck = new HashMap< String, Check >();
public static void invokeChecks( String[] checks, String[] configFile ) {
for( String check : checks ) {
nameToCheck.get( check ).check( configFile );
}
}
}
解决方案3:
解决方案3与解决方案2类似,但是除了抽象每个检查之外,您还可以抽象出计划检查的每种配置。 然后,每种类型将负责对文件调用所有必需的检查。
public interface ConfigType {
void check( String[] configFile );
}
public class TxtConfig implements ConfigType {
public void check( String[] configFile ) {
// Place calls to all required checks.
// check100( configFile );
// check101( configFile );
}
}
public class XMLConfig implements ConfigType {
public void check( String[] configFile ) {
// Place calls to all required checks for XML configs
// check101( configFile );
// check102( configFile );
}
}
IMO这是一个非常干净的解决方案,可以扩展该接口,在该接口中可以使用每个ConfigType子类来确定可以检查的配置文件。 它还提供了其他两种解决方案无法提供的更高的灵活性。 就像只做某些检查,如果先前的检查“失败”一样。 它还可以减少解决方案2中所需的子类数量。您仍然可以在不同的配置类型之间共享检查方法,而无需进行额外的工作。
一种解决方案是创建一个接口:
public interface Checkable {
void check(String[] configFile);
}
然后创建几个实现此接口的类。 不幸的是,如果您确实需要100多种不同的支票,这将无法很好地扩展。
您可以使用Reflection
。
遵循以下原则:
String chk = checklist[0];
Method checkMethod = Class.getDeclaredMethod(chk);
checkMethod.invoke();
您可以这样使用反射
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
class ReflectionExample {
public static void main(String[] args){
String[] checklist = { "check100", "check101", "check105" };
ReflectionExample example = new ReflectionExample();
for (String methodName : checklist) {
try {
Method method = ReflectionExample.class.getMethod(methodName, String[].class);
String[] configFile = new String[1];
method.invoke(example,configFile);
}catch(Exception e) {
e.printStackTrace();
}
}
}
// ...
public void check100(String[] configFile) { // performs the configFile
// check100
System.out.println("check100");
}
public void check101(String[] configFile) { // performs the configFile
// check101
System.out.println("check101");
}
public void check103(String[] configFile) { // check not applicable to this
// device
System.out.println("check103");
}
}
当然,将为check105抛出异常
警告 :不是最好的方法。
一种简单的方法是使用foreach循环和switch语句:
for (String check: checklist) {
switch (check) {
case "check100": check100();
break;
case "check101": check101();
break;
default: defaultCheck();
break;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.