2013-03-13 14 views
7

Gram z pakietem rJava, ale ponieważ wydaje się, że rJava nie jest świadomy typów generycznych Java, mam problemy z tworzeniem obiektu java z parametrami typu ogólnego. Jeśli mam klasy java takich jak:Generics rJava typ

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

Chciałbym utworzyć obiekt z R sesji używając .jnew() przekazując obiekt B już utworzony (z wystąpienia parametru typu), ale rJava zawsze daje błąd:

java.lang.NoSuchMethodError: <init> 

Czy są jakieś prace?

+0

Jaka jest dokładna składnia, z której korzystasz podczas wywoływania '.jnew()'? Czy przekazujesz mu argumenty?Proszę dokładnie je określić. – Brick

+0

Oto sprawdzony przykład. Musisz pobrać słoik Tetrad z [here] (http://www.phil.cmu.edu/projects/tetrad_download/download/tetrad-5.2.1-3.jar) (19mb) i przykładowy zestaw danych, charity.txt, from [here] (http://www.phil.cmu.edu/projects/tetrad_download/download/workshop/Data/charity.txt). Ustaw w R: 'setwd (" wherever/you/put/the/data/")', 'biblioteka (rJava)', '.jinit (" ścieżka/do/tetrad-5.2.1-3.jar ")'. Wszystkie poniższe prace: 1. 'filename = .jnew (" java/lang/String "," charity.txt ")', 2. 'datafile = .jnew (" java/io/File ", nazwa pliku)', 3. 'reader = .jnew (" edu/cmu/tetrad/data/DataReader ")', –

+0

4. 'delim = J (" edu/cmu/tetrad/data/DelimiterType ")', 5. 'reader $ setDelimiter (delim $ TAB) ', 6.' dataset = reader $ parseTabular (plik danych) '. Ale nie działa: 7. 'gesinstance = .jnew (" edu/cmu/tetrad/search/Ges ", zbiór danych)'. czytnik $ parseTabular zwraca DataSet, a klasa Ges ma zostać utworzona za pomocą argumentu DataSet. Niestety to nie działa. Myślę, że powodem jest to, że Ges implementuje dwa interfejsy: GraphSearch i GraphScorer, a GraphScorer to tylko dwa. W źródle Java: 'publiczny interfejs GraphScorer { double scoreDag (Graph dag); } ' –

Odpowiedz

1

Jest wiele ruchomych części w tym pytaniu. Kopanie poprzez dokumentację dla różnych części, myślę, że trzeba to zrobić na linii, który wybuchł:

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

Kluczową różnicą jest wywołanie .jcast na drugim argumencie. (Nie mam zainstalowanej wersji R, więc nie mogłem tego przetestować - jeśli to nie zadziała, zaktualizuję moją odpowiedź na podstawie opinii, którą możesz przekazać w przypadku nowych komunikatów o błędach.)

A więc pytanie jest "Dlaczego to?" Odpowiedź wydaje się być:

  1. Po stronie Java DataReader.parseTabularData zwraca obiekt z typu DataSet jak wspomniano, ale to nie DataSet interfejs klasy. Oznacza to, że zwracany obiekt jest klasy, która implementuje interfejs DataSet.
  2. Z powodów, które nie są dla mnie oczywiste, pakiet rJava nie radzi sobie dobrze z polimorfizmem. Wymaga to wywołania metod z "dokładnym" podpisem zgodnym z obiektami, które przekazujesz. W tym przypadku będziesz musiał "przerzucić" z jakiejś konkretnej klasy, którą masz do interfejsu DataSet. Zobacz dokumentację dla .jnew (https://www.rforge.net/doc/packages/rJava/html/jnew.html), szczególnie dla argumentów, które oznaczają "...". Odwołuje się do odpowiedniej części dokumentacji dla .jcall (https://www.rforge.net/doc/packages/rJava/html/jcall.html), po czym wyjaśnia objaśnienie wymagania wywołania .jcast (https://www.rforge.net/doc/packages/rJava/html/jcast.html) z kilkoma przykładami.

Błąd, który otrzymałeś java.lang.NoSuchMethodError: <init>, informował, że maszyna JVM nie może znaleźć konstruktora, który wywołałeś. To było tajemniczo wyglądające w przykładzie, który zamieściłeś w komentarzach. (Nawiasem mówiąc, dobrze byłoby edytować pytanie i umieścić tam informacje dla potomności.) Kod z pewnością wygląda dobrze i, znając Javę, intuicyjnie spodziewałem się, że interfejs będzie respektował polimorfizm Javy. Biorąc pod uwagę, że (z jakiegokolwiek powodu) interfejs do R dokonuje "dokładnego" dopasowywania typów bez uwzględniania dziedziczenia, jasne jest, że nie znajdzie konstruktora z powodu nr 1 powyżej.

Wreszcie, nie spotkałem się z żadnymi klasami Javy przy użyciu generycznych w mojej ograniczonej eksploracji Tetradu. Jak się okazało, był to jednak kompletny czerwony śledź. Jeśli będzie to problemem w przyszłości, prawdopodobnie będziesz chciał sprawdzić "Typ Erasure" (https://docs.oracle.com/javase/tutorial/java/generics/erasure.html). Jeśli łączyłeś się z Javą i C, C++, Fortranem, dowolnym językiem, który Java uważa za "natywny", radziłbyś sobie z rodzajami generycznymi w kodzie rodzimym, zajmując się typowymi formularzami. Interfejs rJava może być jednak inny, ponieważ wygląda na to, że wpadł on w ten sam ogólny typ struktury, który wyzwolił cię z obecnego problemu. (Być może godne własnej nagrody później!)

+0

Dziękujemy! Rozwiązuje to problem, przed którym stanąłem, i daje mi lepsze zrozumienie rJava (i samej Javy). Nie jestem pewien, jak edytować pytanie, ponieważ nie zadałem pierwotnego pytania, a odkryłeś, że chodzi o zupełnie inny problem niż to, z czym miałem do czynienia. Być może powinienem zadać to dwuczęściowe pytanie? –