Отправить «готовую к вызову» функцию на java

#java #function

#java #функция

Вопрос:

Есть ли в Java способ отправить «указатель», скажем, на другую функцию, чтобы функция могла вызывать ее, когда захочет?

На данный момент я отправляю все аргументы и использую интерфейс, который реализует функцию, которая должна быть вызвана, следующим образом:

 //assumes effectThisPacket has already validated this packet.
public void sendEffectPacket(DatagramSocket s, Packet p, SendReceiveInterface i){ //affect the packet based on effect, then send it (if it's not dropped)
    switch(effect){ //REFACTOR fix this once effect is an enum
    case (1): //drop packet
        //do nothing, the packet disappears
        break;
    case (2): //delay packet
        try {
            Thread.sleep(effectArgs[0]);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        i.sendFromSocket(s, p); //I want to fix this line
        break;
    case (3): //duplicate packet
        break;

    }
}
  

Итак, мой вопрос — есть ли способ отправить i.sendFromSocket(s,p) (или другую функцию, если я хочу) моей sendEffectPacket функции в качестве аргумента, чтобы все, что мне нужно было сделать, это call (function) не беспокоиться о том, каковы аргументы? Есть ли способ предварительно сконструировать весь фрейм стека, который будет сгенерирован, отправить его и поместить в стек, когда я буду готов?

Комментарии:

1. Оберните ее в лямбда-выражение с аргументом 0.

2. Runnable r = () -> i.sendFromSocket(s,p);

3. Отменить инициализацию — это имеет смысл. Что я принимаю в качестве типа аргумента на стороне определения функции? shmosel — это кажется небезопасным, возможно, я ошибаюсь.

4. @BrydonGibson Я предлагал именно то, что написал шмозель. Это тип, который можно выполнить. Почему это было бы небезопасно? В данном случае используется злоупотребление Runnable. Это не имеет никакого отношения к потокам.

5. Хорошо, я увидел runnable и сразу подумал, что вы создаете новый поток. У меня нет опыта работы с лямбда-функциями, но я согласен, что решение является идеальным. Спасибо

Ответ №1:

Java 8 приходит на помощь. Описанный метод представляет собой обратный вызов, и передача результатов или вызов ее с обратным вызовом были громоздкими.

Вам понадобится меньше классов:

 public void sendEffectPacket(DatagramSocket s, Packet p,
        BiConsumer<DatagramSocket, Packet> i) {

    i.accept(s, p);
  

И вызывающий может использовать лямбды:

 sendEffectPacket(s, p, (socket, packet) -> {
    System.out.printf("S: %s, P: %s%n", socket, packet);
});