简体   繁体   中英

Is there a way to invoke a static method of a class using a string which has the name of the class?

I have an array of strings containing names of classes. Is it possible to invoke the static methods of the actual class using the 'name of the class' in the string array.

public class SortCompare {

    // There are classes called 'Insertion', 'Selection' and 'Shell' which have a 
    //   method called 'sort'
    private static String[] algorithm = {  "Insertion", "Selection", "Shell"};

    public static double timeTheRun(String alg, Comparable[] a) {

        for (int i = 0; i < algorithm.length; i++)
            if (alg.equalsIgnoreCase(algorithm[i])) {
                Stopwatch timer = new Stopwatch();

                 // I want to invoke one of Insertion.sort(), Selection.sort()
                 // or Shell.sort() depending on the value of 'alg' here

                 break;
            }
                return timer.elapsedTime();
        }

I could forget about the array of strings and simple use a if-else block to invoke them.

         if (alg.equals("Insertion"))
            Insertion.sort(a);
         else if (alg.equals("Selection"))
            Selection.sort(a);
         else if (alg.equals("Shell"))
            Shell.sort(a);

But I will keep implementing other sorts and variations of them in future and every time I will have to make changes in multiple places(The above if-else loop, the help message of my program). If the former approach is possible then I'll just have to insert an extra string to the array every time.

The better way to implement this would be to create a common interface for your sorting algorithms:

interface SortingAlgorithm {
    public void sort(Comparable[] a);
};

Then have all your algorithms implement that interface:

class InsertionSort implements SortingAlgorithm {
    public void sort(Comparable[] a) {
        // sort here using insertion-sort
    }
};

and make the parameter to your method take an implementation of the interface:

public static double timeTheRun(SortingAlgorithm alg, Comparable[] a) {
    // all the setup
    alg.sort(a);
    // all the post-processing
}

You would then call that method like this:

timeTheRun(new InsertionSort(), data);

This has the disadvantage that you cannot make the sorting-routine a static method, though.

Alternative If you insist on static methods, make your routine take a class-object as parameter:

public static double timeTheRun(Class algClass, Comparable[] a) {
    // all the setup
    algClass.getMethod("sort", Comparable[].class).invoke(null, a);
    // all the post-processing
}    

Note that you will either have to add a try-catch-block or a throws declaration for the various exceptions that the reflection methods can throw. Then you can call it like this:

timeTheRun(InsertSort.class, data);

Yes, this is possible via reflection.

Method method = Class.forName(alg).getMethod("sort", Comparable[].class);
method.invoke(null, a);

However, using reflection is not a very clean approach. You should consider changing your code to have your sorting algorithms implementing an interface containing this sort method. That way you could directly invoke the sort method in a clean way.

Yes, what you need is the factory pattern .

Make a common interface shared between the sort algorithms. Then make a factory object that returns the right algorithm based on the input. You can input a enum , string , .class , whatever you like.

public interface Sort {
    void sort(Comparable[] a)
}

public class SortFactory {
    public static sort getSorter(SortType type) {
        if (type == SortType.INSERTION)
            return new InsertionSort();
        if (type == SortType.SELECTION)
            return new SelectionSort();
        if (type == SortType.SHELL)
            return new ShellSort();
    }
}


public enum SortType {
    INSERTION,
    SELECTION,
    SHELL
}

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