(import 'java.io.DataOutputStream)
(import 'java.io.ByteArrayOutputStream)
(defn- ->bytes
"将 Java 基本类型转换为字节表示形式。"
[write v]
(let [output-stream (ByteArrayOutputStream.)
data-output (DataOutputStream. output-stream)]
(write data-output v)
(seq (.toByteArray output-stream))))
(defn int->bytes [n]
(->bytes
#(.writeInt ^DataOutputStream %1 %2)
n))
(defn int->bytes-ref [n]
(->bytes
#(.writeInt %1 %2)
n))
user=> (int->bytes 5)
(0 0 0 5)
user=> (int->bytes-ref 5)
(0 0 0 5)
user=> (int->bytes (inc Integer/MAX_VALUE))
IllegalArgumentException Value out of range for int: 2147483648 clojure.lang.RT.intCast (RT.java:1115)
user=> (int->bytes-ref (inc Integer/MAX_VALUE))
(-128 0 0 0)
因此,看起来给 DataOutputStream 添加类型提示会导致字节码调用 RT.intCast,因为该值太大而抛出异常。在反射的情况下,我们在运行时找到 writeInt 方法,然后不调用 RT.intCast,而是允许长类型在不进行范围检查的情况下向下转换。
看来我们在这两种情况下都应调用 RT.intCast?