Java可以将方法存储在数组中吗?

Posted

技术标签:

【中文标题】Java可以将方法存储在数组中吗?【英文标题】:Can Java store methods in arrays? 【发布时间】:2011-01-11 11:27:50 【问题描述】:

好吧,我写了一些代码,我所做的只是 for 循环,但改变了我调用的方法。我尝试使用 for 循环,所以它会更整洁(出于好奇,看看它是否可以完成),但是当我这样做时它不会编译,因为它无法识别其中的项目我认为,数组作为一种方法。这就是我所拥有的:

String[] moveArray = moveRight,moveDown,moveLeft,moveUp;
for (i = 0; i < 4; i++) 
    while (myWumpus.moveArray[i]) 
        myWumpus.moveArray[i];
        generator.updateDisplay();
    

当我尝试编译时,我得到了

not a statement myWumpus.moveArray[i]();
';' expected myWumpus.moveArray[i]();

(指while循环中的第一条语句)

所以,我认为这可能是因为我将其设为字符串类型的数组?有类型方法吗?这是可能吗?欢迎任何解决方案:)。此外,我可以使用 4 个 while 循环使其工作,因此您无需向我展示该解决方案。谢谢!

【问题讨论】:

【参考方案1】:

您不能将方法直接存储在数组中。但是,您可以存储对象,这些对象以不同的方式实现相同的方法。例如:

Mover[] moveArray = new RightMover(), new DownMover() new LeftMover(), new UpMover() ;
for (i = 0; i < 4; i++) 
    while (myWumpus.moveArray[i]) 
        moveArray[i].move();
        generator.updateDisplay();
    

【讨论】:

很好的解释。我现在会坚持四个循环,但如果它不止于此,我会试试这个! 一种变体是使用枚举。需要在方法调用中通过参数传递被操作的对象,而不是构造函数。【参考方案2】:

是的,您可以使用Reflection 将方法存储在数组中,但是在这种情况下您真正想要做的可能是使用polymorphism。

作为与您的问题相关的多态性示例 - 假设您创建了如下接口:

public interface MoveCommand 
    void move();

然后您可以按如下方式创建实现:

public class MoveLeftCommand implements MoveCommand 
    public void move() 
        System.out.println("LEFT");
    

等等。对于其他移动选项。然后,您可以将它们存储在 MoveCommand[]List&lt;MoveCommand&gt; 之类的集合中,然后遍历数组/集合,在每个元素上调用 move(),例如:

public class Main 

    public static void main(String[] args) 
        List<MoveCommand> commands = new ArrayList<MoveCommand>();
        commands.add(new MoveLeftCommand());
        commands.add(new MoveRightCommand());
        commands.add(new MoveLeftCommand());

        for (MoveCommand command:commands) 
            command.move();
        
    


多态非常强大,上面是一个非常简单的例子,叫做Command Pattern。享受 Wumpus World 实施的其余部分:)

【讨论】:

【参考方案3】:

您不能在 Java 中将方法存储在数组中,因为方法不是 Java 中的一等对象。这是一些人更喜欢使用 Python、Scheme 等其他语言的原因。

解决方法是创建一个包含一个方法的接口,然后创建四个实现该接口的类——MoveRight、MoveLeft 等...类。然后您可以将这些类的实例存储在您的数组中并以相同的方式调用它们。

【讨论】:

+1 是的,在大多数情况下,接口比使用反射要好。 :-) java.lang.reflect.Method 是一流的对象,但我同意您提出的一般解决方案 @Brian:是的,但它是一个表示方法的对象,它实际上并不是一个方法本身。您不能“调用” Method 的实例(您在实例上调用方法)。【参考方案4】:

你不能调用这样的方法。但是你可以使用反射:

只需将while循环中的第一行更改为:

Method m = myWumps.getClass().getMethod(moveArray[i]); // if the method is void
m.invoke(myWumps);

(您必须声明/捕获一些异常)

但您最好避免反射,并改用Command pattern。

【讨论】:

为什么最好避免反射?反思是耗时还是记忆力过大?上面的代码看起来很整洁。【参考方案5】:

Java 8 及更高版本的更新答案-

自从在 Java 8 中引入 lambda expressions 和 method references 以来,现在可以将各种方法存储在变量中。一个主要问题是arrays don't currently support generic objects in Java,这使得将方法存储在数组中不太可行。但是,它们可以存储在其他数据结构中,例如 List

因此,对于一些简单的示例,您可以编写如下内容:

List<Comparator<String>> stringComparators = new ArrayList<>();
Comparator<String> comp1 = (s1, s2) -> Integer.compare(s1.length(), s2.length());
stringComparators.add(comp1);

List<Consumer<String>> consumers = new ArrayList<>();
Consumer<String> consumer1 = System.out::println;
consumers.add(consumer1);

然后循环/迭代 List 以获取方法。

【讨论】:

以上是关于Java可以将方法存储在数组中吗?的主要内容,如果未能解决你的问题,请参考以下文章

我可以将 JavaScript 函数存储在数组中吗?

您可以将函数存储在 PHP 数组中吗?

Jvm(28),理解升级----java中的基本数据类型一定存储在栈中吗

在 derby 数据库中存储数组

ArrayList中的toArray方法

JGit:我可以在不检查的情况下找出某个特定标签是不是存在于 Git 存储库中吗?