Reproducible minimal example
here: https://github.com/alexander-yakushev/generics-reflection-bug . Clone
it and do `lein run`.
The example is small enough to paste it here. So we have a class called
AbstractStorage:
abstract class AbstractStorage<T> {
T thingToStore;
public AbstractStorage(T thingToStore) {
this.thingToStore = thingToStore;
}
public T get() {
return thingToStore;
}
}
It is a non-public abstract generic-typed class. It's only use is to store
some object of the type T, and give out that object when get() is called.
Simple enough.
Then we have a concrete implementation of that class, StringStorage:
public class StringStorage extends AbstractStorage<String> {
public StringStorage(String thingToStore) {
super(thingToStore);
}
}
It is even simpler. It just extends the abstract class and says that the
type of object it will hold is a String. The constructor just passes the
call up to AbstractStorage.
Now comes the trouble. When you try to do the following from Clojure:
(.get (StringStorage. "hello"))
It fails with:
Exception in thread "main" java.lang.IllegalArgumentException: Can't call
public method of non-public class: public java.lang.Object
bug.AbstractStorage.get(),
compiling:(/tmp/form-init579170128820879977.clj:1:72)
at clojure.lang.Compiler.load(Compiler.java:7239)
at clojure.lang.Compiler.loadFile(Compiler.java:7165)
at clojure.main$load_script.invoke(main.clj:275)
at clojure.main$init_opt.invoke(main.clj:280)
at clojure.main$initialize.invoke(main.clj:308)
at clojure.main$null_opt.invoke(main.clj:343)
at clojure.main$main.doInvoke(main.clj:421)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:383)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
Caused by: java.lang.IllegalArgumentException: Can't call public method of
non-public class: public java.lang.Object bug.AbstractStorage.get()
at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:88)
at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:28)
at bug.core$_main.doInvoke(core.clj:9)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.Var.invoke(Var.java:375)
at user$eval2912.invoke(form-init579170128820879977.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6782)
at clojure.lang.Compiler.eval(Compiler.java:6772)
at clojure.lang.Compiler.load(Compiler.java:7227)
... 11 more
I tried to type-hint the call, but neither of the following work:
(.get ^AbstractStorage (StringStorage. "hello"))
(.get ^StringStorage (StringStorage. "hello"))
I suppose hinting to AbstractStorage should have helped, but because the
actual class has a generic type, the classes mismatch and Reflector is
still invoked. Any ideas what to do with this?
P.S.: As I was finishing writing this. I found the reported bug on JIRA:
CLJ-1243 <http://dev.clojure.org/jira/browse/CLJ-1243>. Still, I suppose it
will be useful to have a minimal reproducible example for this bug, and to
remind it exists.
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.