2013-03-13 202 views
7

我一直在玩rJava包,但由於似乎rJava沒有意識到Java泛型類型,所以我在使用泛型類型參數創建java對象時遇到困難。如果我有一個Java類,如:rJava泛型類型

public class A<T> { 
    private B<T> b; 
    public A(B<T> b) { 
     this.b = b; 
    } 
} 

我想通過使已經創建(與實例化的類型參數)B的對象來創建使用.jnew() R對話的一個目的,但是rJava總是給錯誤:

java.lang.NoSuchMethodError: <init> 

有沒有解決此問題的方法?

+0

當你調用'.jnew()'時,你使用的確切語法是什麼?你傳遞了它的參數嗎?請正確指定它們。 – Brick 2015-09-15 18:44:10

+0

這是一個成功的例子。您需要從[here](http://www.phil.cmu.edu/projects/tetrad_download/download/tetrad-5.2.1-3.jar)(19mb)和示例數據集下載Tetrad jar, charity.txt,從[這裏](http://www.phil.cmu.edu/projects/tetrad_download/download/workshop/Data/charity.txt)。設置在R:'setwd(「where/you/put/the/data /」)', 'library(rJava)', '.jinit(「path/to/tetrad-5.2.1-3.jar 「)'。所有以下工作:1.'filename = .jnew(「java/lang/String」,「charity.txt」)',2.'datafile = .jnew(「java/io/File」,文件名)', 3.'reader = .jnew(「edu/cmu/tetrad/data/DataReader」)', – 2015-09-15 21:59:19

+0

4.'delim = J(「edu/cmu/tetrad/data/DelimiterType」)',5.'reader $ setDelimiter (delim $ TAB)',6.'dataset = reader $ parseTabular(datafile)'。但以下方法不起作用:7.'gesinstance = .jnew(「edu/cmu/tetrad/search/Ges」,數據集)'。 reader $ parseTabular返回一個DataSet,並且Ges類應該使用DataSet參數創建。不幸的是,這是行不通的。我認爲這是因爲Ges實現了兩個接口GraphSearch和GraphScorer,GraphScorer只是一個接口。在Java源代碼中:'public interface GraphScorer double scoreDag(Graph dag); }' – 2015-09-15 22:04:32

回答

1

這個問題中有很多移動部件。通過對各部分的文檔進行挖掘,我認爲你需要做這個,打破了行:

gesinstance = .jnew("edu/cmu/tetrad/search/Ges", .jcast(dataset, "edu/cmu/tetrad/data/DataSet")) 

的主要區別是在第二個參數調用.jcast。 (我沒有安裝R,所以我無法測試 - 如果它不起作用,我會根據您提供的新錯誤消息的任何反饋更新我的答案。)

那麼問題是「爲什麼?」答案似乎是:

  1. 在Java方面,DataReader.parseTabularData返回與DataSet類型的對象,你注意,但DataSet是一個接口不是類。這一定意味着返回的實際對象是一些實現接口的類。
  2. 由於我不明白的原因,rJava軟件包並沒有很好地處理多態性。它要求您調用具有與您傳遞的對象「精確」簽名匹配的方法。在這種情況下,您將需要從任何特定的課程「上傳」到接口DataSet。請參閱.jnewhttps://www.rforge.net/doc/packages/rJava/html/jnew.html)的文檔,特別是它們用「...」表示的參數。這指的是.jcallhttps://www.rforge.net/doc/packages/rJava/html/jcall.html)文檔的相應部分,然後通過一些示例說明了呼叫.jcasthttps://www.rforge.net/doc/packages/rJava/html/jcast.html)的要求。

你得到的錯誤java.lang.NoSuchMethodError: <init>告訴你JVM找不到你調用的構造函數。在你發表評論的例子中,這看起來很神祕。 (順便說一下,編輯你的問題可能是個好習慣,並且在那裏爲後代包含這些信息。)代碼當然看起來是正確的,並且,在瞭解Java的情況下,我直觀地期望接口尊重Java的多態性。鑑於(無論出於何種原因),與R的接口在不考慮繼承的情況下進行「確切」類型匹配,很明顯,由於上述原因#1,它不會找到構造函數。

最後,在我對Tetrad的有限探索中,我實際上沒有遇到任何使用泛型的Java類。事實證明,這是一個完整的紅鯡魚,但。如果將來會成爲問題,您可能需要查看「類型擦除」(https://docs.oracle.com/javase/tutorial/java/generics/erasure.html)。如果您正在Java和C,C++,Fortran之間進行交互,Java認爲任何語言都是「native」,那麼您將通過處理類型擦除表單來處理本機代碼中的泛型。 rJava界面可能會有所不同,因爲這似乎屬於相同的一般類型的結構,導致您在當前問題上出現問題。 (以後也許值得擁有它自己的賞金!)

+0

謝謝!這解決了我所面臨的問題,並使我更好地理解rJava(以及Java本身)。我不確定如何編輯這個問題,因爲我沒有提出原始問題,而且您發現它與我面臨的問題有着完全不同的問題。也許我應該把它作爲一個兩部分的問題? – 2015-09-17 13:30:50