【问题标题】:How can I get the name of the defined class in a parent static method in Groovy如何在 Groovy 的父静态方法中获取已定义类的名称
【发布时间】:2012-06-04 21:02:15
【问题描述】:

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

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

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

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

问题是我不知道如何分辨父类的静态主方法中实际的实例化类是什么。

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

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

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

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

"new HardCodedChildClassName()"

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

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

groovy HardCodedChildClassName dir

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

【问题讨论】:

  • 静态方法在 Java 中不是继承的,只是隐藏的——这就是你的编辑注释的意思吗?
  • 是的,因为静态方法不是继承的,我认为这在 Java 中是不可能的——我希望 Groovy 有一些技巧。目前我的解决方案是在我的子类中放置一个 main ,它将自身的实例转发到父启动器类,但我宁愿不必这样做。

标签: reflection groovy static


【解决方案1】:

我不确定这是否可能。无论如何,如果是的话,它很可能是一个丑陋的黑客。我建议使用这种替代方法:不要使用静态的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()    
    }
}

【讨论】:

  • 实际上,这正是我所希望的那种基于 groovy 的解决方案,而且效果很好。如果它不必具有该注释会很好......我将研究Java / groovy可能隐藏它们的替代位置。我将把这个问题留待一段时间,给其他人机会,但我并不期待有比这更好的解决方案。
猜你喜欢
  • 1970-01-01
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
  • 2012-03-08
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
  • 1970-01-01
相关资源
最近更新 更多