2012-01-15 5 views
18

、私はこの方法で(.jarファイルに)外部のクラスをロード:スカラ - 動的オブジェクト/クラスローディングJavaでは

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という名前traitModule.scala)を持っている:

trait Module { 
    def name: String 
} 

object Module { 
    lazy val ModuleClassName = "my.module.ExModule" 
} 

私はその後、module.jarにそれをコンパイルし、Moduleを拡張するモジュールを記述します。

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 

私はそれをテストする場合:

- >は常にfalseを返します。

この問題で私を助けてくれますか?

編集

私はExModuleobject(ないclass)であるので、それはあると思います。しかし、それをclassに変更すると、classLoader.loadClass(...)java.lang.NoClassDefFoundErrorになります。 ExModuletraitから拡張されているからだと思います。

私は混乱しています。誰でも私を助けてくれますか?

編集

clazz.isInstanceOf[Class[Module]]//or Class[Byte], or Class[_]... 
true

戻ります。

+0

私はあなたがClassNotFoundExceptionを取得していたときにそれをクラスにすることに近づいたと思います。 module.jarを参照したときにパスが正しく取得されていることを確認できますか?それが特性から拡張されているという事実は、何の違いもありません.ExModuleはクラスです(その場合)。 –

+0

はい私は 'module.jar'へのパスが正しいと確信しています。メソッド 'classLoader.loadClass(...)'はうまく動作します( 'ExModule'が' object'の場合)。 –

+0

(javapなどを介して)コンパイルされたバイトコードを見ることができますか? Scalacには$ sや他の奇妙な名前を追加するという面白い習慣があり、ExModuleはコンパイルされたバージョンでちょっと別の名前を持っているかもしれません。また、scalacにjavaコードを印字するようにscalacに依頼することもできます(私は今オプションを覚えていません)。 – Rogach

答えて

8

おっと...私は答えを得ました。

私はScalaのチームはに正しい方法を提供する前に、この方法は一時的なものであると思います外部のjarファイルからobject/class/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 Module\n", clazzExModule) } 

編集

私はクラスとしてよりよい設計ExModuleを思います。 Moduleので

if (clazz.isAssignableFrom(classOf[Module])) 

:あなたはそれを逆の方法を行うことはできません

var clazz = classLoader.loadClass(Module.ModuleClassName) 
if (classOf[Module].isAssignableFrom(clazz)) 
    ... 

注:などなどのjarファイルからロードした後、私はそれを確認することができますこの場合、trait/objectisAssignableFrom()は機能しません。

0
+0

ありがとう、私はこの1つを投稿する前にその質問を読んでいます。しかし、私はまだ混乱しています:-(。私はもう一度やっています... –

関連する問題