Using JRuby 1.6.0RC1
I've got a java file like
package com.foo.bar
public class Foo
{
Foo(String baz){}
}
If, in jruby, I do
com.foo.bar.Foo.new "foo"
then I get
TypeError: no public constructors for Java::ComFooBar::Foo
Reading http://jira.codehaus.org/browse/JRUBY-5009 makes me thing this is WAD, but how do I get around the problem without altering the java file?
Subclassing Foo and then instantiating I get a different error:
ArgumentError: Constructor invocation failed: tried to access method com.foo.bar.Foo.(Ljava/lang/String;)V from class org.jruby.proxy.com.foo.bar.Foo$Proxy0
EDIT:
Got it to work through help from Headius on IRC. The following works, but could possibly be more intelligent:
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
There indeed is no public constructor for that. The constructor is package level.
How do other Java classes outside the package com.foo.bar
acquire objects of this type? It may be there is already a factory in that package that produces this class by calling the package-scoped constructor, and that you could call from JRuby.
If not, you could make a public factory class in that package, possibly in Java, possibly in Ruby, and call this constructor from there.
You might also be able to monkey-patch to add a ruby-accessible constructor or factory method, without having to modify the Java source.
That's because the constructor is has package level access.
You could try to define your ruby class in the same package as the foo class.
In Java you can use the reflection API to do something like:
Constructor constructor = MyClass.class.getConstructor(Class ... paramTypes);
constructor.setAccessible(true);
MyClass myClass = (MyClass)constructor.newInstance(Object ... args);
Not sure you can do that in JRuby, but I'd imagine you could.
There's an oracle guide to this: http://download.oracle.com/javase/tutorial/reflect/member/ctorInstance.html
Guess the only fixes are the one you proposed, or "remove your initializer from the ruby class" (which may be a bug in jruby--shouldn't it call its ancestor no matter what?) or "make the java class initializer protected access" [I'm not sure why jruby disdains package level so much].
http://betterlogic.com/roger/2011/05/javajavamirah-woe/comment-page-1/#comment-5034
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.