19

Possible Duplicate:
Java Pass Method as Parameter

Is it possible to pass a method as a parameter in Java? If I can't what would be the best course of action for the method below without having to repeat code.

public void enterUserInput(javax.swing.JTextField inputField, javax.swing.JTextField   outputField, method rangeChecking){

    String input;
    double output;
    input = inputField.getText();
    output = Double.parseDouble(input);
    if(rangeChecking(output)){
        outputField.setText(input);
        inputField.setText(null);
    }

I will be calling a rangeChecking method from a different class and each time I call the enterUserInput the rangeChecking method will be different

Community
  • 1
  • 1
Indy411
  • 3,666
  • 4
  • 20
  • 19

8 Answers8

32

You should use an interface to do it.

You pass the interface that declares the desired function to the method, and invoke the desired method. The specific method that will be invoked is the one implemented by the implementing class.

It is called the strategy design pattern.

code sample:

public static interface Foo { //this is the interface declaration
    public void print();
}
public static class Bar implements Foo { //Bar is an implementing class
    public void print() {
        System.out.println("Bar");
    } 

}
public static void test(Foo foo) { //the method accepts an interface
    foo.print(); //and invokes it, the implementing class' print() will be invoked.
}
public static void main(String... args) throws Exception {
    test(new Bar()); //invoke test() with the class implementing the interface
}
amit
  • 175,853
  • 27
  • 231
  • 333
  • 2
    Thanks .. learnt something new today .. :) – Amarnath Sep 27 '12 at 08:44
  • 1
    If I had to choose a design pattern that resembles the idea, I'd pick the Command pattern. Stategy sounds way too complex to me, it usually means several implementations exist. – Mister Smith Sep 27 '12 at 13:01
  • @amit why did you declare the interface static? – Celeritas May 28 '14 at 22:35
  • 1
    @Celeritas Because it was an inner class. If you put it not as an inner class (in its own file), there is no need to declare the interface static. Also, since java8 - this answer is kinda obselete, with the introduced [lambda expressions](http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html)\. – amit May 28 '14 at 23:00
8

Create an interface with that method signature, and pass an anonymous subclass of it with your method implementation.

// the interface that contains the method/methods you want to pass
interface MethodWrapper {
    public void method(String s); }

// ...
// in your code
// assuming that "observable" is an object with a method "setCallback" that 
// accepts the callback
// note that your method implementation will have access to your local variables

public void someMethodOfYours() {
    observable.setCallback(new MethodWrapper() {
        public void method(String s) {
            System.out.println(s);
        } }
    );
    // note that your anon subclass will have access to all your contain method 
    // locals and your containing class members, with [some restrictions][1]
}

// in the "observable" class - the class that receives the "callback method"
// ...

if( updated() ) {
    callback.method("updated!"); }

In future versions of java (with the advent of lambdas) you won't have to define the interface and the anonymous inner class - there will be specific lambda syntax which will compile to the equivalent bytecode.

[1] Cannot refer to a non-final variable inside an inner class defined in a different method

Community
  • 1
  • 1
jrharshath
  • 25,975
  • 33
  • 97
  • 127
6

Not as far as I know. This is generally done by making an interface that has the method you want and passing a class that implements that interface in.

public interface IRangeCheck
{
    boolean check(double val);
}

public class RangeChecker implements IRangeCheck
{
    public boolean check(double val)
    {
        return val > 0.0;
    }
}

...
    public void blabla(..., IRangeCheck irc)
    {
        ...
        if(irc.check(output))
           ...
    }
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
CrazyCasta
  • 26,917
  • 4
  • 45
  • 72
5

You may use java reflection.

public void enterUserInput(javax.swing.JTextField inputField, javax.swing.JTextField   outputField, String methodName){

String input;
double output;
input = inputField.getText();
output = Double.parseDouble(input);
Method m = this.getClass().getDeclaredMethod(methodName, Double.class);

if((Boolean)m.invoke(this, output)){
    outputField.setText(input);
    inputField.setText(null);
}
retromuz
  • 809
  • 9
  • 26
  • 2
    You should handle the case when the required method belongs to an ancestor class and/or the compatible method has a different signature. `void foo(double d)` won't be match by `getDeclaredMethod` if you pass it `Double.class`. – Stephan Sep 27 '12 at 08:19
  • 1
    You should really use language features such as the solution with interfaces presented by others rather than reflection. Reflection is not type safe and it's slower than regular method calls. – Jesper Sep 27 '12 at 09:08
4

There are ways you can do this using the Reflection but that's best avoided. What you want to do is create an interface like:

    public interface RangeChecker {

    boolean rangeChecking(double input);


}

Then create implementations for each of your range checking methods:

    public class SomeRangeCheck implements RangeChecker {

    public boolean rangeChecking(double input) {
        // do something
    }

}

Then your other method's signature becomes:

public void enterUserInput(JTextField inputField, JTextField   outputField, RangeChecker rangeChecking)

That you can pass any of your objects that implement the RangeChecker interface.

Vipul Purohit
  • 9,807
  • 6
  • 53
  • 76
lotophage
  • 163
  • 7
2

You can create an Interface that defines the needed method, and pass an object of a class that implements that interface. Often, anonymous classes are used for that.

interface Worker {
    public void callMe();
}

public function callWorker(Worker w) {
    w.callMe();
}

callWorker(new Worker() {
    public void callMe() {
        System.out.println("Hi there!");
    });
Ridcully
  • 23,362
  • 7
  • 71
  • 86
1

you can't pass method's in java.

what you do is declaring a interface, and getting as a parameter a class that implements the interface, this way you could invoke the function through the parameter.

you could, in your code create a anonymous class.

elyashiv
  • 3,623
  • 2
  • 29
  • 52
1

No, passing methods as argument is not possible.

I guess, best approach is to create an interface, write a class that implements that (modify the implementation as you need) and pass the object of the class as an argument.

Also you could use reflection, pass the methodName as a String to your method. and use reflection to call that method.

Hope this helps :-)

Mukul Goel
  • 8,387
  • 6
  • 37
  • 77