#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);
});