2013-03-13 199 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