繁体   English   中英

有没有办法使用名称为 class 的字符串调用 class 的 static 方法?

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

我有一个包含类名的字符串数组。 是否可以使用字符串数组中的“类名称”调用实际 class 的 static 方法。

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();
        }

我可以忘记字符串数组并简单地使用 if-else 块来调用它们。

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

但我将在未来继续实现它们的其他种类和变体,每次我都必须在多个地方进行更改(上面的 if-else 循环,我的程序的帮助消息)。 如果前一种方法可行,那么我只需每次都向数组中插入一个额外的字符串。

实现这一点的更好方法是为您的排序算法创建一个通用接口:

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

然后让所有算法实现该接口:

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

并使您的方法的参数采用接口的实现:

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

然后,您将像这样调用该方法:

timeTheRun(new InsertionSort(), data);

但是,这样做的缺点是您不能将排序例程设为 static 方法。

替代方案如果您坚持使用 static 方法,请让您的例程将类对象作为参数:

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

请注意,您必须为反射方法可能抛出的各种异常添加 try-catch-block 或 throws 声明。 然后你可以这样称呼它:

timeTheRun(InsertSort.class, data);

是的,这可以通过反射实现。

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

但是,使用反射不是一个非常干净的方法。 您应该考虑更改代码以使您的排序算法实现包含此排序方法的接口。 这样你就可以直接以一种干净的方式调用 sort 方法。

是的,您需要的是工厂模式

使排序算法之间共享一个公共接口。 然后制作一个工厂 object 根据输入返回正确的算法。 您可以输入enumstring.class ,无论您喜欢什么。

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
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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