(导入 'java.io.DataOutputStream)
(导入 'java.io.ByteArrayOutputStream)
(定义 ->bytes
"将 Java 基本数据类型转换为字节表示形式。"
[写 v]
(let [输出流 (ByteArrayOutputStream.)
数据输出 (DataOutputStream. 输出流)]
写入数据输出 v)
(转化为 (.toByteArray 输出流))))
(定义 int->bytes [n]
(->bytes
#(写入Int ^DataOutputStream %1 %2)
n))
(定义 int->bytes-ref [n]
(->bytes
#(写入Int %1 %2)
n))
用户=> (int->bytes 5)
(0 0 0 5)
用户=> (int->bytes-ref 5)
(0 0 0 5)
用户=> (int->bytes (+ Integer/MAX_VALUE))
IllegalArgumentException Int值超出范围:2147483648 clojure.lang.RT.intCast (RT.java:1115)
用户=> (int->bytes-ref (+ Integer/MAX_VALUE))
(-128 0 0 0)
看起来,对 DataOutputStream 进行类型注解导致字节码调用 RT.intCast,因为它抛出异常,因为值太大。在反射情况下,我们在运行时找到 writeInt 方法,然后不调用 RT.intCast,而是允许长型向下转换而不进行范围检查。
似乎我们应该在这两种情况下都调用 RT.intCast?