2013-03-21 78 views
2

我正在Clojure中寫簡單的應用程序。我的任務是從用戶那裏獲得實現Runnable接口並調用啓動方法的完全限定類名(Java類)。我的問題是如何運行這種方法,當我不知道類名先驗?基於this我已經嘗試過這樣的事情(在簡單的String類),但我失敗:動態生成名稱的類的調用方法

(defn schedule [parameter] 
    (def class-name (subs parameter 6))  ; get just class name for e.g. java.lang.String 
    (println (.getName class-name))) 

我還發現this但我不太清楚如何使用它,因爲我用它也失敗了。有任何想法嗎?

+0

你可以添加一些示例輸入和期望的輸出的時間表? – 2013-03-21 21:03:39

+0

這只是我需要的一個例子。最後,我將調用我自己的一個實現Java.lang.Runnable的類,所以我將需要調用myClass.start()並將它留下。所以輸出是NULL和輸入是因爲我寫了完全合格的類名(類名與包名) – Blood 2013-03-21 21:08:58

回答

2

如果你想避免使用宏,你可以這樣做:

(defn schedule [name] 
    (let [thread (-> name Class/forName .newInstance Thread.)] 
    (.start thread) 
    thread)) 

然後,您可以用通常的Java方法返回的Thread對象進行交互。

+0

不要打擾這些潛艇。一個關於你的解決方案我如何能夠檢查線程是否開始? – Blood 2013-03-21 21:34:25

+0

對不起,忽略了關鍵的'(Thread。)'步驟!我已經重構了上面的代碼片段來返回線程本身,所以如果需要的話可以與之交互。 – dfreeman 2013-03-21 21:41:46

+0

好的,謝謝。我會檢查明天,因爲今天我就像殭屍:D – Blood 2013-03-21 21:59:53

2

你可以用宏或eval來做到這一點。通常更喜歡一個宏來評估。

user> (defmacro runnerizer [class-name] 
      `(~(symbol (str class-name "/" "start"))))              
#'user/runnerizer                              
user> (macroexpand-1 '(runnerizer "myClass"))                       
(myClass/start) 
+0

哦,太棒了。我該如何檢查線程是否已經啓動?還有更多,我必須把我的課程放在我的Clojure應用程序中才能看到? – Blood 2013-03-22 09:43:15

+0

我想你可能不得不使用eval來使它在運行時傳入的類名工作 - 或者有另一種方法可以在編譯之後推遲宏展開? – Alex 2013-03-22 14:47:10

+0

Class/forName方法應該在運行時以及eval中工作。鑑於我打算爲dfreeman的答案投票,因爲我偏袒使用eval – 2013-03-22 18:22:00