如何将数组链接到方法

时间:2018-12-31 16:33:01

标签: java arrays syntax

这个问题主要是针对Java的,但是如果它适用于所有面向对象的编程语言,那很好。

我想知道是否存在一种将数组值链接到特定方法的方法。我有一个包含许多方法的程序,当在巨型if脚本中存在特定条件时,该方法就会运行。我发现这很慢而且效率低下。我想知道是否可以创建一个数组,其中每个值都链接到要执行的相应方法。

例如:如果我有一个0到99之间的数字,并且我想根据我选择的任何数字运行某种方法。我可以制作一个具有相应方法的数组,而不是制作具有100种不同情况的if脚本吗?所有方法都在一个类中,每个数字都有自己的方法。看起来像这样:

int num = 73;
methods[num](parameters);

我不知道这样的事情是否可能。任何帮助将不胜感激!

7 个答案:

答案 0 :(得分:4)

定义一个接口(将其命名为ScriptTask),以定义要执行的方法(将其称为execute)。创建ScriptTask的数组任务。然后使用tasks[num].execute(parameters)

示例:

@FunctionalInterface
interface ScriptTask {
    void execute(String s, int i);
}

class Script {

    private ScriptTask[] tasks;

    Script() {
        this.tasks = new ScriptTask[2];
        this.tasks[0] = this::foo;
        this.tasks[1] = this::bar;
    }

    private void foo(String s, int i) {
        System.out.println(s);
    }

    private void bar(String s, int i) {
        System.out.println(i);
    }

    void run() {
        for (int i = 0; i < tasks.length; i++) {
            tasks[i].execute("hello", i);
        }
    }

    public static void main(String[] args) {
        new Script().run();
    }
}

请注意,如果您在一个类中确实有100个不同的方法,则明确表明应将其重构为几个不同的更简单的类,以使其更易于阅读,理解和测试。上面是重构的第一步:您可以将每个方法重构为实现ScriptTask接口的单独类。

答案 1 :(得分:1)

您需要传递定义了方法的类的Object,从数组中获取方法名称并传递参数。仅发布所需的代码。

public static Object invokeExactMethod(Object object, String methodName, Object... args) {
        if (null == args) {
            args = ArrayUtils.EMPTY_OBJECT_ARRAY;
        }
        int arguments = args.length;
        Class<?>[] parameterTypes = new Class[arguments];
        for (int i = 0; i < arguments; i++) {
            parameterTypes[i] = args[i].getClass();
        }
        return invokeExactMethod(object, methodName, args, parameterTypes);
    }


    invokeExactMethod() is method provided my MethodUtils class of apache commons.

希望这会有所帮助.. !!

答案 2 :(得分:0)

在我正在研究的程序中,我通过使用覆盖的方法创建构造函数来实现了这一目标。

public class Script 
{
    public Script()
    {

    }

    public void run()
    {

    }
}

public class TestScript extends Script
{
    public TestScript()
    {

    }

    public void run()
    {
        //This Method overwrites the run method of script. This is where your code goes.
    }
}

public class Main
{
    public static Script test = new TestScript();

    public static void main(String[] args)
    {
        test.run();
    }
}

答案 3 :(得分:0)

可以创建一个接口来保存要运行的方法,例如:

public interface MethodRunner {
   public void run();
} 

定义数组并添加MethodRunner的实例。

MethodRunner[] methodsRunners = new MethodRunner[n];
methodsRunners[0] = new MethodRunner() {
      @Override
      public void run() {
        // some method here 
      }
};
methodsRunners[0] = ... 
      . 
      . 
methodsRunners[n] = ... 

并通过以下方式运行它:

methodsRunners[n].run();

答案 4 :(得分:0)

好吧,我认为我们可以利用Reflection来实现此目标,如下所述”

1。)用于存储有关方法的信息的类

public class MethodInfo {

    public String methodName;
    public Class<?>[] params;
}

2。)由所有方法组成的类

public class Task {

    public void method1(int x, ......){

    }
    And So On..
}

3。)主类创建数组并使用它。在这里,我们可以使用Reflection来访问数组中的方法并调用它们。

public class MainClass {

    public static void main(String[] args) {

        MethodInfo firstMethod = new MethodInfo();
        firstMethod.methodName = "method1";
        firstMethod.params = Array OF Parameter Types(.class values)

        MethodInfo[] methods = new MethodInfo[10];
        methods[1] = firstMethod;

        java.lang.reflect.Method method = Task.class.getMethod(methods[1].methodName, methods[1].params);
        method.invoke(new Task(), param1, param2,....);
    }
}

答案 5 :(得分:0)

除了JB Nizet的答案外,还可以使用其他语法变体:

    this.tasks = new ScriptTask[4];
    this.tasks[0] = this::foo;
    this.tasks[1] = this::bar;
    this.tasks[2] = (String s, int i) -> {
        System.out.println(s);
    };
    this.tasks[3] = (String s, int i) -> System.out.println(s);

甚至:

   this.tasks = new ScriptTask[] {
        this::foo,
        this::bar,
        (String s, int i) -> {
            System.out.println(s);
        },
        (String s, int i) -> System.out.println(s)
    };

答案 6 :(得分:0)

  

我想知道是否存在一种将数组值链接到特定方法的方法。

您可以使用反射来生成方法数组。但是,这是“不理想的解决方案”,因为它将使您的代码难以维护。所以,我不得不说这不是一个好习惯,但是在这里。

package methodarray;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MethodArray {
    public static void main(String[] args) {
        Method[] arrayOfMethods = new Method[100];
        try {
            //...You will need to add the methods by their name, you can use for loops to add them quickly
            arrayOfMethods[1] = MethodArray.class.getDeclaredMethod("someMethodName");
            arrayOfMethods[2] = MethodArray.class.getDeclaredMethod("someOtherMethod");
            //...
        } catch (NoSuchMethodException | SecurityException ex) {
            //this can throw an Exception if the method is not found, handle it here
        }
        //now to call a method from the array just do
        try {
            arrayOfMethods[1].invoke(MethodArray.class);
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
            //...handle exceptions
        }
    }

    public void someMethodName(){
        //...logic
    }

    public void someOtherMethod(){
        //...logic
    }
}

这将帮助您随意调用这些方法,但是请记住,出于安全性考虑,java在使用反射时可能会抛出一些期望。要发送其他参数,只需调用arrayOfMethods[n].invoke(MethodArray.class, args[]);

  

这个问题主要是针对Java的,但是如果它适用于所有面向对象的编程语言,那很好。

为解决这些类型的常见情况,我们使用 设计模式 ,模式是针对常见情况的经过测试的解决方案。所有回答都表明您应该“使用接口”实际上是在试图帮助您实现这一目标,您可能可以使用的模式称为Command Pattern,您可以阅读有关here的信息。因为您已经说过您不熟悉使用接口,所以理解或阅读该模式可能没有用。 (我个人总是推荐Head First Design Patterns作为有关模式的入门书籍。)

一旦您了解了命令模式,就可以简单地生成命令数组,这是一个更好的OO解决方案,请记住这一点。我不会举一个例子,因为如果您对如何使用接口没有清晰的想法,我很难理解,请阅读它们,那将是值得的!!!