Programming Clojure学习笔记——与Java一起工作

3.3  使用Clojure创建和编译Java类
Clojure的所有对象都实现了Java的特定接口:
1. Clojure数据结构实现了Java集合接口
2. Clojure函数实现了Runnable和Callable接口

Clojure可以在需要时很方便地在磁盘上生成一次性的代理或类,使用必要的一些Java代码片段。

创建Java代理
在Clojure中,可以使用代理来扩展一个类:
(proxy class-and-interfaces super-cons-args & fns)
示例:
(def print-element-handler
    (proxy [DefaultHandler] []
        (startElement
        [uri local qname atts]
        (println (format "Saw element: %s" qname)))))
说明:
1. proxy创建了代理类的一个实例;
2. proxy机制是完全通用的,可以用来任意Java对象
user=> (.start (Thread.
              (proxy [Runnable] [] (run [] (println "I ran!")))))
user=> I ran!
3. 在Java中必须实现接口的所有方法,但在Clojure中不必如此,如
user=> (proxy [Callable] [])
#<Object$Callable clojure.proxy.java.lang.Object$Callable@11e0c13>
如果忽略方法实现,Clojure将提供一个默认实现,该实现抛出异常UnsupportedOperationException,如
user=> (.call (proxy [Callable] []))
java.lang.UnsupportedOperationException: call (NO_SOURCE_FILE:0)

Clojure的函数都自动实现Runable和Callable接口,下面举例说明:
; 正常用法:调用匿名函数
user=> (#(println "foo"))
; 调用run方法通过Runnable接口
user=> (.run #(println "foo"))
; 调用call方法通过Callable接口
user=> (.call #(println "foo"))
三种调用方法都输出foo

编译到硬盘
reader.tasklist类Clojure源代码:
(ns reader.tasklist
    (:gen-class
    :extends org.xml.sax.helpers.DefaultHandler
    :state state
    :init init)
    (:use [clojure.contrib.duck-streams :only (reader)])
    (:import [java.io File]
             [org.xml.sax InputSource]
             [org.xml.sax.helpers DefaultHandler]
             [javax.xml.parsers SAXParserFactory]))
(defn -main [& args]
   (dosseq [arg args]
       (println (task-list arg))))
(defn task-list [arg]
   (let [handler (new examples.tasklist)]
      (.. SAXParserFactory newInstance newSAXParser
          (parse (InputSource. (reader (File. arg)))
              handler))
      @(.state handler)))
(defn -init[]
   [[] (atom [])])
(defn -startElement
  [this uri local qname atts]
  (when (= qname "target")
    (swap! (.state this) conj (.getValue atts "name"))))
说明:
(1) :gen-class 指示Clojure生成Java类reader.tasklist
(2) :extends 指示生成类继承DefaultHandler(实现接口用:implements语句)
(3) Clojure生成Java类将类状态隔离到一个单独的状态结构,:state语句指定状态结构变量
(4) :init语句指定类初始化函数,初始化函数返回Java需要的基类构造函数参数和Clojure使用的初始状态结构
(5) Clojure生成reader.tasklist类,并创建方法;这些方法代理你提供的函数,每个方法代理一个相同名字的函数,方法名以连接符(-)为前缀

Clojure提供compile函数:
(compile lib)
compile函数对运行环境要求很苛刻:
(1) 要编译的lib必须从classpath可以访问
(2) 类文件生成目录(*complile-path*)必须在classpath中,默认为Clojure的启动目录

Clojure为类本身生成一个class文件,为类的每个函数或方法生成一个类,名字包含__init的类很特殊,它在第一次加载时执行lib的顶级代码。Clojure的这种模块性允许我们在运行时动态替换单个函数。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值