繁体   English   中英

Java-如何以类名和方法名作为字符串从另一个类调用方法

[英]Java - How to invoke a method from another class, with the class name and method name as a string

定期调用此方法

public static void stynax(String N[]) {
    if (N[1].equals("echo")) { echo.s(); main(); }
    if (N[1].equals("detectos")) { detectos.s(); main(); }
    if (N[1].equals("getuser")) { getuser.s(); main(); }
    if (N[1].equals("exit")) { exit.s(); main(); }
    if (N[1].equals("makefile")) { makefile.s(); main(); }
    if (N[1].equals("cd")) { cd.s(); main(); }
    if (N[1].equals("system")) { system.s(); main(); }
    main();
}

我该如何调用所有这些方法

system.s();
echo.s();

等等,通过查看该类是否存在,然后调用相应的方法。 N [1]始终是类名。 存储该方法的类位于名为main的类中,而所调用的类位于另一个称为Commands的程序包中。

在尝试制作Class变量时,我似乎总是会收到此错误,我认为这是主要问题。

at java.net.URLClassLoader.findClass(URLClassLoader.java:381)

因此,它永远不会调用该方法。

为了简化。

1)程序将类名作为字符串获取为N [1]

2)看该类是否存在

3)如果该类存在,则以类N [1] .s()的名称调用它;

编辑:导入使用import java.io.ByteArrayOutputStream; 导入java.io.FileWriter; 导入java.io.IOException; 导入java.io.PrintStream; 导入java.io.PrintWriter; 导入java.lang.reflect.InvocationTargetException; 导入java.lang.reflect.Method; 导入java.util.Arrays;

import cgameing.Commands.FileBrowser;
import cgameing.Commands.banner;
import cgameing.Commands.cd;
import cgameing.Commands.detectos;
import cgameing.Commands.echo;
import cgameing.Commands.exit;
import cgameing.Commands.getuser;
import cgameing.Commands.makefile;
import cgameing.Commands.system;

编辑结束:

这对任何想做同样事情的人都有效

(Class.forName("commands."+N[1])).getDeclaredMethod("s", null).invoke(null,null);

感谢大家

您将需要使用反射。 请尝试以下操作。 如果您的班级位于其他包中,请使用完全限定的班级名称而不是"XYZ"

import java.lang.reflect.*;
import java.lang.*;

public class ReflectionTest {
 public static void main(String[] args)throws NoSuchMethodException,
 ClassNotFoundException,
 IllegalAccessException,
 InvocationTargetException {
  (Class.forName("XYZ")).getDeclaredMethod("ABC", null).invoke(null,null);
 }
}

class XYZ
{
  public static void ABC()
  {
    System.out.println("Lulz");
  }
}  

对于您的用例,您的类位于commands包中(如您在注释中所述)。 完全限定的名称将是commands.classname

(Class.forName("commands."+N[1])).getDeclaredMethod("s", null).invoke(null,null);

您可以使用反射。 您在数组中有类名。

您可以使用“类”和“方法”类。 类可以确定该类是否存在,并且方法可以用于调用您需要调用的方法。

    try {
            Class<?> c = Class.forName(N[1]);
            Object t = c.newInstance();

            Method[] allMethods = c.getDeclaredMethods();
         for (Method m : allMethods) {
              String mname = m.getName();
// if name matches use invoke method.
            }
        } catch (ClassNotFoundException x) {
         //handle exception
        }

如果需要查看更多详细信息,请咨询API。

我建议您尽可能避免使用反射。 最好是定义您希望看到的命令-理想情况下是在enum

例如:

enum Command {
    CD(FileSystem::cd),
    EXIT(Application::exit),
    MAKEFILE(FileSystem::createFile),
    ...

    private final Runnable runnable;

    Command(Runnable runnable) {
        this.runnable = runnable;
    }

    public void run() {
        runnable.run();
    }
}

如果愿意,您仍然可以使用名称来获取命令(如果在枚举中找不到该值,则自动引发异常-大概是您想要的):

Command.valueOf(commandString.toUpperCase()).run();

或者直接调用命令,而不必知道它们委托给哪个方法:

Command.MAKEFILE.run();

假设您将在某处有一个if语句列表, if最好将其封装在一个enum中,该enum比嵌入方法名称更为明确。

好的,每个人似乎都建议反射,至少有一种替代方法可以进行反射,具体取决于您在编译时是否知道类和方法的名称。

因此,可以说我们在某些类中有此方法:

    public void changeDirectory(String args) {

    //do something
}

如果它们是已知的,则可以轻松地使用方法引用:

    HashMap<String, Consumer<String[]>> commands = new HashMap<>();
    commands.put("cd", SomeClass::changeDirectory);
    commands.get("cd").accept(args);

缺点是方法签名必须相同... 另一方面,如果您仍然知道确切的方法,则可以使用switch语句直接调用它们...

如果要动态地进行操作,则可以使用MethodHandles代替反射。 其优点是,他们将只在创作检查访问一次,并有一些其他的优化, 应该让他们比在大多数情况下,反映速度更快。

    Class<?> dynamicallyFoundClass = Class.forName("some.package.SomeClass");
    Class<?> fixedClass = SomeClass.class;
    String methodName = "changeDirectory";
    MethodType type = MethodType.methodType(void.class, String.class);

    handles.put("cd", lookUp.findStatic(dynamicallyFoundClass, methodName, type));

    handles.get("cd").invoke(args);

但是,您必须使用的方法的复杂程度取决于您在编译时知道的内容以及在运行时必须找到的内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM