Programming Clojure學習筆記——與Java一起工作

3.1  調用Java
Clojure提供了簡單直接的語法調用Java代碼:創建對象,調用方法,訪問靜態方法和屬性。

訪問構造函數,方法和屬性
Clojure提供了new形式調用構造函數創建實例
(new classname)
下面的代碼創建Ramdom對象,賦給rnd變量:
user=> (def rnd (new java.util.Random))
#'user/rnd

使用特殊形式(.)調用方法:
(. class-or-instance member-symbol & args)
(. class-or-instance (member-symbo & args))
下面的代碼調用rnd的nextInt方法:
user=> (. rnd nextInt)
-1663716284
特殊形式(.)可以作用在靜態或實例屬性和方法上。如:
user=> (. Math PI)

可以通過import顯示引入類,使用時就可以不需要用類全名稱:
(import [& import-lists])

在Clojure中調用Java大致分爲以下幾步:
1. 引入類名
2. 創建實例
3. 訪問實例屬性
4. 調用實例方法

語法糖
大部分Java形式都有一個縮寫形式,如
(1) new形式可以縮寫爲Classname.
(new Random)可以縮寫爲(Random.)
(2) 對於靜態域,縮寫形式Classname/membername,如
(. Math PI)可以縮寫爲Math/PI
(3) 同樣對於靜態方法,也可以縮寫爲(Classname/membername),如
(System/currentTimeMillis)
(4) .形式的縮寫形式.methodOrFieldName,如
(. rnd nextInt)可以縮寫爲(.nextInt rnd)
(5) 多次連續調用的縮寫形式(.. class-or-instance form & forms),如
(.getLocation (.getCodeSource (.getProtectionDomain (.getClass '(1 2)))))可以縮寫爲
(.. '(1 2) getClass getProtectionDomain getCodeSource getLocation)
(6) 在同一對象上調用多個方法(doto class-or-inst & member-access-forms),如
(doto (System/getProperties)
   (.setProperty "name" "Stuart")
   (.setProperty "favoriteColor" "blue"))

使用Java集合
Clojure提供make-array函數創建Java數組:
創建一維數組 (make-array class length),如
user=> (make-array String 5)
#<String[] [Ljava.lang.String;@5f6303>

創建多維數組 (make-array class dim & more-dims),如
user=> (make-array String 2 2)
#<String[][] [[Ljava.lang.String;@766a24>

可以使用seq將任意Java數組包裝稱Clojure序列,如
user=> (seq (make-array String 5))
(nil nil nil nil nil)

Clojure還提供了一序列類似int-array的函數用來創建Java基礎類型數組,如
user=> (int-array 5)
#<int[] [I@1742700>

Clojure提供了一組Java數組基本操作函數:
aset 設置Java數組項值
一維數組 (aset java-array index value)
多維數組 (aset java-array index-dim1 index-dim2 ... value)

aget 獲取Java數組項值
一維數組 (aget java-array index)
多維數組 (aget java-array index-dim1 index-dim2 ...)

alength獲取數字長度
(alength java-array)

示例:
user=> (defn painstakingly-create-array []
   (let [arr (make-array String 5)]
     (aset arr 0 "Painstaking")
     (aset arr 1 "to")
     (aset arr 2 "fill")
     (aset arr 3 "in")
     (aset arr 4 "arrays")
     arr))
#'user/painstakingly-create-array
user=> (aget (painstakingly-create-array) 0)
"Painstaking"
user=> (alength (painstakingly-create-array))
5

to-array函數直接將集合轉化爲數組
(to-array sequence)
說明:轉換的結果爲Object數組
user=> (to-array ["Easier" "array" "creation"])
#<Object[] [Ljava.lang.Object;@cf66b>

into-array函數也能將集合轉換爲數組,並且可以指定數組元素類型
(into-array type? seq),如:
user=> (into-array String ["Easier" "array" "creation"])
#<String[] [Ljava.lang.String;@110c31>
如果忽略類型參數,into-array則根據第一個元素猜測數組元素的類型,如:
user=> (into-array ["Easier" "array" "creation"])
#<String[] [Ljava.lang.String;@110c31>

amap函數轉換Java數組的每個元素
(amap a idx ret expr)
amap創建數組的克隆,並綁定到變量ret,對數組a每一個元素執行expr表達式,idx綁定到數組元素索引,最後返回克隆的數組,如
user=> (def strings (into-array ["some" "strings" "here"]))
#'user/strings
user=> (seq (amap strings idx _ (.toUpperCase (aget strings idx))))
("SOME" "STRINGS" "HERE")

areduce函數類似amap,但可以返回值任意
(areduce a idx ret init expr)
areduce開始用init初始化ret,然後對每一個數組a元素計算表達式expr,將計算結果賦給ret返回。如
user=> (areduce strings idx ret 0 (max ret (.length (aget strings idx))))
7
上面的代碼計算數組strings中,最長字符串的長度

便利函數
1. memfn 創建匿名函數包裝Java方法,使其在Clojure中能像Clojure函數那樣使用,如
user=> (map (memfn toUpperCase) ["a" "short" "message"])
("A" "SHORT" "MESSAGE")
還可以寫成如下形式:
user=> (map #(.toUpperCase %) ["a" "short" "message"])
("A" "SHORT" "MESSAGE")

2. instance? 類似Java的instanceof,檢測一個對象是否是某個類的實例,如
user=> (instance? Integer 10)
true

3. format包裝了Java的format方法,格式化字符串
(format fmt-string & args),如
user=> (format "%s ran %d miles today" "Stu" 8)
"Stu ran 8 miles today"
說明:佔位符詳細參考Java相關文檔

4. bean包裝JavaBean將其轉換爲不可變的Clojure映射
(bean java-bean),如
user=> (import '(java.security MessageDigest))
java.security.MessageDigest
user=> (bean (MessageDigest/getInstance "SHA"))
{:provider #<Sun SUN version 1.6>, :digestLength 20, :class java.security.Messag
eDigest$Delegate, :algorithm "SHA"}
user=> (:digestLength (bean (MessageDigest/getInstance "SHA")))
20
發佈了134 篇原創文章 · 獲贊 12 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章