如何将`static final`常量从Java类拉入Clojure命名空间?

Joe*_*way 7 clojure java-interop

我试图用Clojure绑定包装Java库.Java库中的一个特定类定义了一堆静态最终常量,例如:

class Foo {
    public static final int BAR = 0;
    public static final int SOME_CONSTANT = 1;
    ...
}
Run Code Online (Sandbox Code Playgroud)

我有一个想法,我可以检查类并将这些常量拉入我的Clojure命名空间,而不是明确地指出def每一个.

例如,而不是像这样明确地连接它:

(def foo-bar Foo/BAR)
(def foo-some-constant Foo/SOME_CONSTANT)
Run Code Online (Sandbox Code Playgroud)

当模块加载时,我将能够检查Foo类并动态连接foo-barfoo-some-constant在我的Clojure命名空间中.

我认为这样做有两个原因:

A)在将新常量添加到Foo类中时自动引入新常量.换句话说,在Java接口添加新常量的情况下,我不必修改我的Clojure包装器.

B)我可以保证常量遵循更多Clojure-esque命名约定

我并没有真的卖掉这个,但是要求扩展我对Clojure/Java互操作的知识似乎是个好问题.

谢谢

Jür*_*zel 3

遗憾的是,宏clojure.contrib.import-static不允许导入所有静态最终字段。您必须提供要导入的字段列表。

这个宏是import-static的惯用包装:

(ns stackoverflow
  (:use clojure.contrib.import-static)
  (:import (java.lang.reflect Modifier)))

(defmacro import-static-fields
  "Imports all static final fields of the class as (private) symbols
  in the current namespace.

  Example: 
      user> (import-static-fields java.lang.Integer)
      #'user/TYPE
      user> MAX_VALUE
      2147483647

  Note: The class name must be fully qualified, even if it has already
  been imported."
  [class]
  (let [final-static-field? (fn [field]
                  (let [modifiers (.getModifiers field)]
                (and (Modifier/isStatic modifiers) (Modifier/isFinal modifiers))))
    static-fields (map #(.getName %)
               (filter
                final-static-field?
                (.. Class (forName (str class)) getFields)))]
    `(import-static ~class ~@static-fields)))
Run Code Online (Sandbox Code Playgroud)