user8724610
user8724610

Reputation:

Runnable with a method parameter

Is it possible to have a method parameter in Runnable like this one:

public Runnable createRunnable(Method a_void_method) {
    Runnable runnable = new Runnable() {
        public void run() {
            //a_void_method
        }
    };
    return runnable;
}

Or is there any way to do like that?

Upvotes: 5

Views: 7243

Answers (4)

Sweeper
Sweeper

Reputation: 270980

Runnable represents a method that takes no parameters and returns void. If you want to represent a method that does take parameters, consider using Consumer and BiConsumer.

Or maybe you are asking how to convert from a Consumer to a Runnable, try this:

private static <T> Runnable toRunnable(Consumer<? super T> consumer, T parameter) {
    return () -> consumer.accept(parameter);
}

Upvotes: 4

M. le Rutte
M. le Rutte

Reputation: 3563

The Runnable you are creating doesn't differ from any other anonymous, nested, class. Thus you can pass any 'effectively final' object reference to it. In your case the Method reference is just fine.

However a Method needs an instance or a class to operate on, otherwise the method doesn't know which polymorphic method to call, nor which data to pass.

If your Java version is pre-8 you need to pass the object instance to your createRunnable:

public Runnable createRunnable(Object instance, Method method) {
   return new Runnable() {
       try {
           method.invoke(instance);
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                 // handle exception
                 throw new RuntimeException(e);
            }
   };
)

In Java-8 and later you could use a lambda method reference, removing the need to create a function:

Runnable r = () -> { 
            try {
                method.invoke(instance);
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                 // handle exception
                 throw new RuntimeException(e);
            }
        };

or, if you know the method and instance already you could just as well use

Runnable r = object::method;

Upvotes: 4

Ousmane D.
Ousmane D.

Reputation: 56423

You can use Runnable to represent a void-returning method taking no parameters like this.

public Runnable createRunnable(Runnable a_void_method) {
        Runnable runnable = new Runnable() {
            public void run() {
                a_void_method.run();
            }
        };
        return runnable;
}

or a more compact form:

public Runnable createRunnable(Runnable a_void_method) {
      return () -> a_void_method.run();           
}

or using method reference.

public Runnable createRunnable(Runnable a_void_method) {
       return a_void_method::run;
}

Further, you might not even need to wrap the logic of a_void_method in a method instead you can assign it directly inline:

Runnable runnable = ClassName::a_void_method; 

If you want to represent a void-returning method taking parameters then look into Consumer or BiConsumer or a specific specialization of it.

Upvotes: 0

Alexey Romanov
Alexey Romanov

Reputation: 170723

If you really have a Method obtained by reflection,

 public void run() {
     a_void_method.invoke(instance_to_invoke_on);
     // or if method is static,
     // a_void_method.invoke(null);
 }

Otherwise, you may be looking for lambdas, and for method references in particular:

class X {
    void a_method() { ... }
}

X x = ...
Runnable runnable = x::a_method;

Upvotes: 0

Related Questions