Scala – 动态对象/类加载
在Java中,通过这种方式加载外部类(在.jar文件中):
ClassLoader classLoader = new URLClassLoader(new URL[] { new File("module.jar").toURI().toURL()}); Class clazz = classLoader.loadClass("my.class.name"); Object instance = clazz.newInstance(); //check and cast to an interface,then use it if (instance instanceof MyInterface) ... 它工作正常 ==================== 现在我想在Scala中做同样的事情。我有一个名为Module(Module.scala)的特质: trait Module { def name: String } object Module { lazy val ModuleClassName = "my.module.ExModule" } 我写了一个模块扩展模块,然后将其编译到module.jar中: package my.module import Module object ExModule extends Module {} 然后我加载这个代码: var classLoader = new URLClassLoader(Array[URL]( new File("module.jar").toURI.toURL)) var clazz = classLoader.loadClass(Module.ModuleClassName) 工作正常但是如果我创建新的实例,我得到这个例外: java.lang.InstantiationException: my.module.ExModule 如果我测试: clazz.isInstanceOf[Module] – >总是返回false。 那么你能帮我解决这个问题吗? 编辑 我猜是因为ExModule是一个对象(不是类)。但是当我将它改为class时,classLoader.loadClass(…)引发一个java.lang.NoClassDefFoundError。我猜这是因为ExModule从一个特质扩展了。 我很困惑。有人可以帮我吗 编辑 clazz.isInstanceOf[Class[Module]]//or Class[Byte],or Class[_]... 返回true。 解决方法
糟糕…我得到了答案。
借鉴: > http://stackoverflow.com/a/8868537/942821(再次感谢Neil)。 ==================== 我猜这个方法是临时的,Scala团队提供正确的方式从外部jar文件加载一个对象/类/ trait …。还是因为我找不到正确的方法。但目前这有助于我解决问题。 var classLoader = new java.net.URLClassLoader( Array(new File("module.jar").toURI.toURL),/* * need to specify parent,so we have all class instances * in current context */ this.getClass.getClassLoader) /* * please note that the suffix "$" is for Scala "object",* it's a trick */ var clazzExModule = classLoader.loadClass(Module.ModuleClassName + "$") /* * currently,I don't know how to check if clazzExModule is instance of * Class[Module],because clazzExModule.isInstanceOf[Class[_]] always * returns true,* so I use try/catch */ try { //"MODULE$" is a trick,and I'm not sure about "get(null)" var module = clazzExModule.getField("MODULE$").get(null).asInstanceOf[Module] } catch { case e: java.lang.ClassCastException => printf(" - %s is not Modulen",clazzExModule) } 就这样 :-) 编辑 我最好设计ExModule作为一个类。从jar文件加载后,我可以像下面这样查看: var clazz = classLoader.loadClass(Module.ModuleClassName) if (classOf[Module].isAssignableFrom(clazz)) ... 注意: 你不能做相反的方式: if (clazz.isAssignableFrom(classOf[Module])) 因为Module是一个trait / object,所以在这种情况下isAssignableFrom()将不起作用。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |