jruby + нет публичного конструктора - PullRequest
1 голос
/ 03 февраля 2011

Использование JRuby 1.6.0RC1

У меня есть файл Java, как

package com.foo.bar

public class Foo
{
Foo(String baz){}
}

Если в jruby я делаю

com.foo.bar.Foo.new "foo"

тогда я получу

TypeError: no public constructors for Java::ComFooBar::Foo

Чтение http://jira.codehaus.org/browse/JRUBY-5009 заставляет меня думать, что это WAD, но как мне обойти проблему, не изменяя java-файл?

Создание подкласса Foo, а затем создание экземпляра Я получаю другую ошибку:

ArgumentError: Конструктор Ошибка вызова: попытался получить доступ метод com.foo.bar.Foo (Ljava / языки / String;). В из класса org.jruby.proxy.com.foo.bar.Foo $ Proxy0

РЕДАКТИРОВАТЬ:

Получил работу через помощь от Headius на IRC. Следующие работы, но, возможно, могут быть более умными:

 def package_local_constructor klass,*values
    constructors = klass.java_class.declared_constructors
    constructors.each do |c|
      c.accessible = true
      begin
        return c.new_instance(*values).to_java
      rescue TypeError 
        false
      end
    end
    raise TypeError,"found no matching constructor for " + klass.to_s + "(" + value.class + ")"
  end

Ответы [ 4 ]

3 голосов
/ 04 февраля 2011

Там действительно нет публичного конструктора для этого. Конструктор уровня пакета.

Как другие классы Java вне пакета com.foo.bar получают объекты этого типа? Возможно, в этом пакете уже есть фабрика, которая создает этот класс, вызывая конструктор области действия пакета, и который можно вызвать из JRuby.

Если нет, вы можете сделать общедоступный фабричный класс в этом пакете, возможно, на Java, возможно на Ruby, и вызвать этот конструктор оттуда.

Вы также можете использовать monkey-patch для добавления доступного в ruby ​​конструктора или фабричного метода без необходимости изменения исходного кода Java.

2 голосов
/ 04 февраля 2011

Это потому, что конструктор имеет доступ на уровне пакета.

Вы можете попытаться определить свой класс ruby ​​в том же пакете, что и класс foo.

См .: Назначение пакета Java для класса JRuby

0 голосов
/ 01 июня 2011

Полагаю, единственные исправления - это то, что вы предложили, или «удалите ваш инициализатор из класса ruby» (что может быть ошибкой в ​​jruby - разве он не должен вызывать своего предка, несмотря ни на что?) Или «сделайте javaинициализатор класса защищенный доступ "[Я не уверен, почему jruby так пренебрегает уровнем пакета].

http://betterlogic.com/roger/2011/05/javajavamirah-woe/comment-page-1/#comment-5034

0 голосов
/ 04 февраля 2011

В Java вы можете использовать API отражения, чтобы сделать что-то вроде:

Constructor constructor = MyClass.class.getConstructor(Class ... paramTypes);
constructor.setAccessible(true);
MyClass myClass = (MyClass)constructor.newInstance(Object ... args);

Не уверен, что вы можете сделать это в JRuby, но я думаю, вы могли бы.

Существует руководство для оракула: http://download.oracle.com/javase/tutorial/reflect/member/ctorInstance.html

...