1

I'm new to Java. I want rewrite some Python code to Java to achieve basically the same functions. One part in my Python code is to execute the functions in sequence. Can I create a similar collection of methods in Java?

process_workflow.py

workflow = [
    stage1,
    stage2,
    stage3
]

def process_workflow(workflow: list):
    for stage in workflow:    # each 'stage' is a method
        stage()

The methods of each stage are defined in another Python script. stages.py

def stage1():
    ...

def stage2():
    ...

def stage3():
    ...

My tentative Java code:

class Stages {
    void stage1() {
    }
    void stage2() {
    }
    void stage3() {
    }
}
class Main {
    public static void main(String[] args) {
        Stages stage_obj = new Stages();

        Collection workflow = new ArrayList();
        workflow.add(stage_obj.stage1);
        workflow.add(stage_obj.stage2);
        workflow.add(stage_obj.stage3);

        Iterator workflowIterator = workflow.iterator();
        // ...

    }
}
D Emma
  • 317
  • 1
  • 3
  • 12

2 Answers2

4

You can do it in Java 8+ with Functional Interfaces and Method References.

In your case, a void method with no parameters and no throws clause, your methods match the Runnable interface method:

@FunctionalInterface
public interface Runnable {
    void run();
}

So your code would be:

Stages stage_obj = new Stages();
List<Runnable> workflow = Arrays.asList(
    stage_obj::stage1,
    stage_obj::stage2,
    stage_obj::stage3
);
void processWorkflow(List<Runnable> workflow) {
    for (Runnable stage : workflow)
        stage.run();
}

If the methods are static, e.g. they don't need access to instance fields, your code would be:

List<Runnable> workflow = Arrays.asList(
    Stages::stage1,
    Stages::stage2,
    Stages::stage3
);

The processWorkflow method would still be the same.

As you can see, that closely matches your Python code, but it is fully type-safe.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • https://stackoverflow.com/questions/23958814/functional-interface-that-takes-nothing-and-returns-nothing. Look at the comments on this similar answer. They are informative. – raviiii1 Apr 27 '19 at 18:50
0

I would use reflection:

public static void main(String[] args) throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    Stages stage_obj = new Stages();

    Collection<java.lang.reflect.Method> workflow = new ArrayList<java.lang.reflect.Method>();
    workflow.add(stage_obj.getClass().getDeclaredMethod("stage1"));
    workflow.add(stage_obj.getClass().getDeclaredMethod("stage2"));
    workflow.add(stage_obj.getClass().getDeclaredMethod("stage3"));

    Iterator<java.lang.reflect.Method> workflowIterator = workflow.iterator();
    while(workflowIterator.hasNext()) {
        workflowIterator.next().invoke(stage_obj);
    }
}
Cardinal System
  • 2,749
  • 3
  • 21
  • 42