【问题标题】:clojure java interop for com.google.cloud.storage.StorageImplcom.google.cloud.storage.StorageImpl 的 clojure java 互操作
【发布时间】:2019-07-18 08:27:28
【问题描述】:

尝试与 https://github.com/googleapis/google-cloud-java/blob/master/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java#L139 进行一些 java 互操作 - 带有字节数组的 create 方法。

我的repl中有:

user=> (->> s r/reflect :members 
               (filter #(instance? clojure.reflect.Method %)) 
               (filter #(:public (:flags %))) 
               (filter #(= (str (:name %)) "create")) 
               (print-table [:name :flags :parameter-types]))

|  :name |              :flags |                                                                                           :parameter-types |
|--------+---------------------+------------------------------------------------------------------------------------------------------------|
| create | #{:varargs :public} |             [com.google.cloud.storage.BlobInfo byte<> com.google.cloud.storage.Storage$BlobTargetOption<>] |

(还有其他的,但这似乎是最相关的。)

还有:

user=> s
#object[com.google.cloud.storage.StorageImpl 0x57fb59c8 "com.google.cloud.storage.StorageImpl@57fb59c8"]
user=> blob-info
#object[com.google.cloud.storage.BlobInfo$BuilderImpl 0x1e8ce729 "com.google.cloud.storage.BlobInfo$BuilderImpl@1e8ce729"]
user=> b
#whidbey/bin "SEVZIE1ZIEdVWQ==“

但是当我打电话给.create时,我得到:

user=> (.create s blob-info (bytes b))

java.lang.IllegalArgumentException: No matching method create found taking 2 args for class com.google.cloud.storage.StorageImpl

如果我尝试添加 nil 作为第三个参数,我会得到与 3 args 相同的错误。

我在这里遗漏了一些明显的东西吗?谢谢!

编辑:How to handle java variable length arguments in clojure? 非常相似,而且更通用(这很好)。这个问题最终是关于一个特定的create 函数签名的具体问题。

【问题讨论】:

  • 你喜欢的函数没有使用两个参数,而是三个。你可以在 java 中只用两个 args 来调用它,因为编译器会小心。 JVM 总是接受第三个参数;该类型的数组,即使为空

标签: java clojure google-cloud-platform clojure-java-interop


【解决方案1】:

我不确定(bytes b) 的语法是否正确(#whidbey/bin 是什么???)。

不妨试试

(byte-array [1 2 3]) 

或类似的。您也可以尝试对参数进行类型提示:

(.create s 
    blob-info
    ^"[B" (byte-array [1 2 3])    ; type-hinted param
)

更新

这是我认为您需要的类型提示示例:

(let [byte-array-obj  (byte-array [1 2 3])
      sss             (java.util.Arrays/toString  ^"[B"  byte-array-obj) ]
    (spyxx byte-array-obj)
    (spyx (type byte-array-obj))
    (spyx (aget byte-array-obj 2))
    (spyx sss))

结果:

byte-array-obj => <#[B #object["[B" 0x26071f95 "[B@26071f95"]>
(type byte-array-obj) => [B
(aget byte-array-obj 2) => 3
sss => "[1, 2, 3]"

请注意,Clojure 有一种简单的方法来键入提示,而无需求助于 java-native "[B" 字符串语法:

(java.util.Arrays/toString ^"[B"  byte-array-obj)  ; type hint using a string
(java.util.Arrays/toString ^bytes byte-array-obj)  ; Clojure "build-in" type hint 

两者是等价的。

【讨论】:

  • github.com/greglook/whidbey - 它带有我在 docker 容器中使用的 repl。转换为字节数组并没有成功。这似乎与 clojure 能够通过其签名在类上找到函数有关,而我在使用正确的咒语来确定它时遇到了麻烦。
【解决方案2】:

答案最终是(来自 clojurians slack 上的 seancorfield)blob-info 是一个 BuilderImpl 内部类并且需要是一个实际的 BlobInfo。有效的代码:

(defn get-storage []
  (-> (StorageOptions/getDefaultInstance)
      (.getService)))

(defn get-blob-info [bucket storage-key]
  (let [content-type "text/plain"
        blob-id (BlobId/of bucket storage-key)
        builder (doto
                  (BlobInfo/newBuilder blob-id)
                  (.setContentType content-type))]

    (.build builder)))

(defn upload-str [bucket storage-key str-to-store]
  (let [storage (get-storage)
        blob-info (get-blob-info bucket storage-key)
        byte-arr (.getBytes str-to-store)]
    (.create storage
             blob-info
             byte-arr
             (into-array Storage$BlobTargetOption []))))

最终不需要类型提示 - 只需要正确排列类型即可。

【讨论】:

  • 啊,很高兴发现这个!谢谢
猜你喜欢
  • 2015-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多