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 clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
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 clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to