Search code examples
clojure

How to instantiate a Stream.Builder class in clojure? (using java 9)


I'm following this example to initiate a Stream.Builder:

http://www.java2s.com/Tutorials/Java/java.util.stream/Stream.Builder/Stream.Builder.build_.htm

(def b (doto (Stream/builder)
          (.accept "a")
          (.accept "b")
          (.accept "c")
          (.accept "d")
          (.accept "e")))

However, I'm getting this:

Unhandled java.lang.IncompatibleClassChangeError
 Method
 java.util.stream.Stream.builder()Ljava/util/stream/Stream$Builder;
 must be InterfaceMethodref constant

Is there anything I'm missing?


Solution

  • quick research led me to this issue: https://dev.clojure.org/jira/browse/CLJ-2284

    so the workaround is as mentioned there:

    (import 'java.util.stream.Stream)
    
    (defmacro interface-static-call
      [sym & argtypes]
      `(let [m# (.getMethod ~(symbol (namespace sym))
                            ~(name sym)
                            (into-array Class ~argtypes))]
         (fn [& args#]
           (.invoke m# nil (to-array args#)))))
    
    (doto ((interface-static-call Stream/builder))
      (.accept "a")
      (.accept "b")
      (.accept "c")
      (.accept "d")
      (.accept "e"))
    
    ;;=> #object[java.util.stream.Streams$StreamBuilderImpl 0x121300ed "java.util.stream.Streams$StreamBuilderImpl@121300ed"]
    

    works for me on java 9

    so i guess we should wait for a fix in clojure.