2

注意:我发现另一个答案表明 Java 会将静态方法调用重定向到它自己的类,即使它是在子类上调用的,所以我想我需要找到一个 Groovy 解决方法,否则它就是不可行的。

这就是问题所在:我创建了一个带有“public static void main”的抽象通用“Launcher”类。这个想法是你扩展它并在你的子类中注释这样的方法:

@Command("Show an explorere shell")
public dir() {
    "explorer".execute()    
}

这个类的父类有一个 main ,它反映了 @Command 注释,如果方法名称与您的参数匹配,则执行它。

问题是我不知道如何在父类的静态 main 方法中判断实际的实例化类是什么。

我很确定某处有一个技巧——“this”在静态中不起作用,堆栈跟踪不包含实际的类,只包含父类,我在类中找不到任何元信息或有帮助的 MetaClass 对象。

目前,我已经通过将子类的名称硬编码到父类的主类中来使其工作,如下所示:

public class QuickCli {
    public static void main(String[] args} {
        (new HardCodedChildClassName())."${args[0]}"()
    }
}

我削减了很多,但这是一般的想法。我想更换

"new HardCodedChildClassName()"

适用于任何扩展此类的类的东西。

鉴于上面的两个代码片段,该命令将从命令行执行为:

groovy HardCodedChildClassName dir

尽管我不希望将所有 @Command 方法都设为静态,但如果必须,我可以这样做,但目前我什至不相信我能做到这一点。

4

1 回答 1

3

我不确定这是否可能。无论如何,如果是的话,它很可能是一个丑陋的黑客。我建议使用这种替代方法:与其使用静态main()入口点,不如制作QuickCli一个Runnable. Groovy 会在启动时自动创建一个实例并调用run()它。

这里的一个小问题是捕获命令行参数。Groovy 通过将它们传递给带有String[]参数的构造函数来处理这个问题。实例化的类需要这个构造函数来捕获 args,但是在 Java 中,构造函数不是继承的。幸运的是,Groovy 有一个InheritConstructors注释可以解决这个问题。

这是一个外观示例:

class QuickCli implements Runnable {
    def args

    QuickCli(String[] args) {
        this.args = args
    }

    void run() {
        "${args[0]}"()
    }
}


@groovy.transform.InheritConstructors
class HardCodedChildClassName extends QuickCli {

    @Command("Show an explorere shell")
    public dir() {
        "explorer".execute()    
    }
}
于 2012-06-04T22:24:39.350 回答