【问题标题】:Groovy way to dynamically instantiate a class from String从 String 动态实例化类的 Groovy 方法
【发布时间】:2011-10-13 18:02:04
【问题描述】:

this question about the Groovy way to dynamically invoke a static method 的回答非常有帮助,但我遇到了以下情况:

我定义了一个简单的 Groovy 类:

class Item {
  def id = 1
  def data = [ "a", "b" ]
}

然后我定义了一个简单的实用程序类,它想要动态加载 Item 类:

class Util {
  static def main(args) {
     def cls = "Item" as Class
     def instance = cls.newInstance()
     println instance.toString()
  }
}

Util.groovy 与 Item.groovy 位于同一文件夹中

当我尝试运行 Util.groovy 时,出现以下错误:

Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: 
Cannot cast object 'Item' with class 'java.lang.String' 
to class 'java.lang.Class' due to: 
java.lang.ClassNotFoundException: Item
        at Util.main(Util.groovy:3)

我可以让它工作的唯一方法是使用 groovyc 预编译 Item.groovy,但这错过了成为 Groovy 的意义 :)

【问题讨论】:

    标签: groovy


    【解决方案1】:

    这有效,使用 underlying GroovyClassLoader:

    def instance = this.class.classLoader.loadClass( 'Item', true, false )?.newInstance()
    

    【讨论】:

    • 您应该将this.class 更改为this.getClass()。一般建议使用完整的方法来避开property or map lookups (or invokeMethod overrides)
    • 当我们知道这不是地图时,为什么还要麻烦?拥抱动态! ;-)
    • 您还可以以 3 种不同的形式将构造函数参数直接提供给 newInstance():映射、数组或逗号列表
    【解决方案2】:

    我只是不得不这样做,并找到了一个有趣的方法——所以我想我会回来提及它。

    我遇到了一个问题,因为我想将一个值传递给 newInstance(使用非默认构造函数),并且所有解决方案似乎都有点工作(我很懒,好吗?)

    无论如何,假设你想创建一个新的 Integer(5)...试试这个:

    c = "java.lang.Integer"
    p = "5"
    def result = Eval.me("return new ${c}(${p})")
    assert(result == 5)
    

    工作得非常好,尽管我确信这是可能的最慢解决方案。具有该方法适用于许多其他情况的优点。

    【讨论】:

    • 看来是 javascript 抄袭 :)
    • @Bill 在智力层面上很有趣,但这真的不像 Abdennour TOUMI 说的那样以一种时髦的方式
    • 我同意,只是为了完整性和易用性而提到它——有时您只是在编写一次性脚本,这很容易记住而且很灵活。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-16
    • 2013-09-08
    • 2013-08-15
    • 2014-01-26
    • 2019-11-08
    • 2017-09-18
    相关资源
    最近更新 更多