我对Java很陌生,所以请彻底。我正在创建一个程序,该程序使用方法库来搜索具有各种正则表达式的文本文件。检查列表可能会根据文本文件的类型(文本文件是网络设备配置文件)而更改。某些检查适用于某些设备,不适用于其他设备。每次检查都是通过调用其方法来执行的。我遇到的问题是因为所有检查都不适用,我不知道哪些检查在运行时才适用。因此,当用户选择要检查的设备时,我需要能够使用运行时创建的列表中的String调用方法。 例如: 我想我需要能够使用String调用方法 我的列表中确定执行哪些检查的内容
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
...
...
} `
我试过看反射,但似乎无法弄明白。如果有更好的方法在不使用反射的情况下执行此操作,请告诉我。
答案 0 :(得分:4)
解决方案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 );
}
}
在考虑这种方法之前,您应该阅读几条警告。我没有添加任何错误处理,这段代码将无法编译。 Reflection 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中所需的子类数量。您仍然可以在不同的配置类型之间共享检查方法,而无需额外的工作。
答案 1 :(得分:0)
一种解决方案是创建一个界面:
public interface Checkable {
void check(String[] configFile);
}
然后创建几个实现此接口的类。不幸的是,如果你真的需要超过100种不同的检查,这种方法就不能很好地扩展。
答案 2 :(得分:0)
您可以使用Reflection
。
这些方面的东西:
String chk = checklist[0];
Method checkMethod = Class.getDeclaredMethod(chk);
checkMethod.invoke();
答案 3 :(得分:0)
您可以像这样使用反射
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会抛出异常
答案 4 :(得分:0)
警告:不是最佳方法。
执行此操作的一个简单方法是使用 foreach 循环和开关语句:
for (String check: checklist) {
switch (check) {
case "check100": check100();
break;
case "check101": check101();
break;
default: defaultCheck();
break;
}
}