简体   繁体   中英

In Java, it is possible to take a line of code as a method argument?

I can't seem to find anything on google for this and I'm not sure it's possible. What I want to do, is pass a line of Java code as an argument to a method. Google only turns up results for passing cmd line arguments to methods, but I want to pass an actual line of code.

Basically I want to pass methodA to methodB except methodA isn't a method, but a line of code. Below is a full example of passing a method to a method using reflection.

public class Relation<T> {

protected Set<Pair<T,T>> pairs = null;

public Relation() {
    this.pairs = new LinkedHashSet<Pair<T,T>>();
}

    /* Next 2 methods are methods for sending methods to methods useing java.lang.reflect.Method */
    public Method getMethod(String name) {
        try {   return Relation.class.getDeclaredMethod(name);
        } catch (Exception e) {} 
        return null;
    }

    public boolean execute(Method method, Object... params) {
        try {   return (Boolean) method.invoke(this, params);
        } catch (Exception e) {}
        return false;
    }

    /* The method I reuse several times so I just put methods inside of it */   
    public boolean pairsTFIterator(Method method)  {
        for(Pair<T,T> x : pairs) {
            boolean bool = false;
            for(Pair<T,T> y : pairs) {
                if(execute(method, x,y))    
                    bool = true; break;
            }
            if(!bool) return false;
        }
        return true;
    }

    /* To be replaced by the line of code*/   
    public static <T> boolean isSymmetricPairs(Pair<T,T> a, Pair<T,T> b) {
        return a.getFirst().equals(b.getSecond()) && a.getSecond().equals(b.getFirst()) ? true :false;
    }

    /* Method that calls others */
    public boolean isSymmetric() {
        return pairsTFIterator(getMethod("isSymmetricPairs"));
    }
}

The above works fine and all, but I want to take it a step further and just forego methods like the "isSymmetricPairs" method by just putting that methods logic line directly in the "pairsTFIterator", like so:

public boolean isReflexive() {  
    return  baseSetTFIterator(
            a.getFirst().equals(b.getSecond()) && a.getSecond().equals(b.getFirst()) ? true :false
    );
}

I'm pretty sure this is impossible, but if there is someway to do it, that would be great.

It sounds like what you are looking for are "first-class functions". Some languages treat functions just like a variable, in the sense that you can assign them to variables and pass them as arguments to other functions. Java 8 will be introducing the concept of lambda expressions which will support this type of functionality.

Also there are other JVM languages that provide this already, including Scala and Groovy to name two of the more popular ones.

Just to give you a flavor of what it looks like, in Groovy you can execute arbitrary functions on each element of a collection by calling the each() method and passing it a closure (a function essentially).

def list = [1, 2, 3, 4]
def printer = { x -> println x } // defines a closure that takes one arg and prints it
list.each(printer) // prints out the elements

def sum = 0
def summer = { x -> sum += x } // defines a closure that takes one arg and adds it to the sum variable
list.each(summer)
println sum // should be 1 + 2 + 3 + 4

Put you code in an anonymos inner class may satisfy your requirement:

    interface PairFilter<T>{
        boolean filter(Pair<T, T> a, Pair<T,T> b);
    }

And in you iterator method:

    public boolean pairsTFIterator(PairFilter filter) {
        for(Pair<T,T> x : pairs) {
            boolean bool = false;
            for(Pair<T,T> y : pairs) {
                if(filter.filter(x,y))    
                    bool = true; break;
                }
                if(!bool) return false;
        }
        return true;
    }

then call it:

    pairsTFIterator(new PairFilter<T>(){
        public boolean filter(Pair<T, T> a, Pair<T,T> b){
            return a.getFirst().equals(b.getSecond()) && a.getSecond().equals(b.getFirst()) ? true :false;
        }
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM