Может ли Java хранить методы в массивах? - PullRequest
8 голосов
/ 31 января 2010

Ну, я написал некоторый код, и все, что я делал, было для циклов, но менял метод, который я вызывал. Я попытался использовать цикл 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)

Итак, я думаю, что это возможно, потому что я делаю это массив типа String? Есть метод типа? Это вообще возможно? Любые решения приветствуются :). Кроме того, я могу заставить его работать, используя 4 цикла while, так что вам не нужно показывать мне это решение. Спасибо!

Ответы [ 5 ]

14 голосов
/ 31 января 2010

Вы не можете хранить методы непосредственно в массивах.Однако вы можете хранить объекты, которые реализуют один и тот же метод по-разному.Например:

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();
    }
}
5 голосов
/ 31 января 2010

Да, вы можете хранить методы в массивах, используя Отражение , однако вполне вероятно, что в этой ситуации вы действительно хотите использовать полиморфизм .

В качестве примера полиморфизма по отношению к вашей проблеме - скажем, вы создали интерфейс следующим образом:

public interface MoveCommand {
    void move();
}

Затем можно создать реализации следующим образом:

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

и т.д.. для других вариантов перемещения. Затем вы можете сохранить их в MoveCommand[] или коллекции, например, List<MoveCommand>, а затем перебрать массив / коллекцию, вызывая 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 :) 1020 *

5 голосов
/ 31 января 2010

Вы не можете хранить методы в массивах в Java, потому что методы не являются первоклассными объектами в Java. По этой причине некоторые люди предпочитают использовать другие языки, такие как Python, Scheme и т. Д.

Обходное решение - создать интерфейс, содержащий один метод, а затем создать четыре класса, реализующих этот интерфейс - классы MoveRight, MoveLeft и т. Затем вы можете хранить экземпляры этих классов в своем массиве и вызывать их одинаково.

4 голосов
/ 31 января 2010

Вы не можете вызывать такие методы. Но вы можете использовать отражение:

Просто измените первую строку в цикле while на:

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

(вам придется объявить / поймать несколько исключений)

Но вам лучше избегать рефлексии, и вместо этого используйте шаблон Command *1009*.

0 голосов
/ 20 января 2019

Обновленный ответ для Java 8 и далее -

С введением лямбда-выражений и ссылок на методы в Java 8 теперь возможно сохранение различных методов в переменных. Одна из основных проблем заключается в том, что массивы в настоящее время не поддерживают универсальные объекты в 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, чтобы получить методы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...