jruby +没有公共构造函数

时间:2011-02-03 16:33:11

标签: java ruby jruby

使用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 /郎/字符串;):V   来自课堂   org.jruby.proxy.com.foo.bar.Foo $ Proxy0

编辑:

通过IRC的Headius帮助解决问题。以下工作,但可能更聪明:

 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 个答案:

答案 0 :(得分:3)

确实没有公共构造函数。构造函数是包级别。

com.foo.bar之外的其他Java类如何获取此类型的对象?可能是该包中已有一个工厂通过调用包范围构造函数生成此类,并且可以从JRuby调用。

如果没有,你可以在该包中创建一个公共工厂类,可能是在Java中,可能在Ruby中,并从那里调用这个构造函数。

您也可以使用monkey-patch来添加ruby可访问的构造函数或工厂方法,而无需修改Java源代码。

答案 1 :(得分:2)

那是因为构造函数具有包级访问权限。

您可以尝试在与foo类相同的包中定义ruby类。

请参阅:Assigning a Java package to a JRuby class

答案 2 :(得分:0)

在Java中,您可以使用反射API执行以下操作:

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

不确定你能否在JRuby中做到这一点,但我想你可以。

有一个oracle指南:http://download.oracle.com/javase/tutorial/reflect/member/ctorInstance.html

答案 3 :(得分:0)

猜猜唯一的解决方案是你提出的那个,或者“从ruby类中删除你的初始化程序”(这可能是jruby中的一个错误 - 不管它叫它的祖先,不管是什么?)或者“make java”类初始化程序保护访问“[我不确定为什么jruby会鄙视程序包级别这么多]。

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