(type-reflect typeref & options)
Alpha - subject to change. Reflect on a typeref, returning a map with :bases, :flags, and :members. In the discussion below, names are always Clojure symbols. :bases a set of names of the type's bases :flags a set of keywords naming the boolean attributes of the type. :members a set of the type's members. Each member is a map and can be a constructor, method, or field. Keys common to all members: :name name of the type :declaring-class name of the declarer :flags keyword naming boolean attributes of the member Keys specific to constructors: :parameter-types vector of parameter type names :exception-types vector of exception type names Key specific to methods: :parameter-types vector of parameter type names :exception-types vector of exception type names :return-type return type name Keys specific to fields: :type type name Options: :ancestors in addition to the keys described above, also include an :ancestors key with the entire set of ancestors, and add all ancestor members to :members. :reflector implementation to use. Defaults to JavaReflector, AsmReflector is also an option.
;;;; Alphabetically list all public static fields in java.lang.Integer
(use 'clojure.reflect)
(->> java.lang.Integer
clojure.reflect/type-reflect
:members
(filter #(instance? clojure.reflect.Field %))
(filter #(:public (:flags %)))
(filter #(:static (:flags %)))
(map #(vector (:name %) (:type %)))
(sort)
(pprint))
;;=> ([BYTES int]
;; [MAX_VALUE int]
;; [MIN_VALUE int]
;; [SIZE int]
;; [TYPE java.lang.Class])
;;;; List class hierarchy for a particular class
(defn class-hierarchy [clazz]
(let [refl (fn [c] (assoc (clojure.reflect/type-reflect c) :name c))]
(loop [type (refl clazz) hierarchy '()]
(let [parent (->> type
:bases
(map refl)
(remove #(:interface (:flags %)))
first)]
(if parent
(recur parent (conj hierarchy (:name type)))
(conj hierarchy java.lang.Object))))))
(pprint (class-hierarchy javax.security.auth.login.CredentialNotFoundException))
;;=> (java.lang.Object
;; java.lang.Throwable
;; java.lang.Exception
;; java.security.GeneralSecurityException
;; javax.security.auth.login.LoginException
;; javax.security.auth.login.CredentialException
;; javax.security.auth.login.CredentialNotFoundException)
(pprint (class-hierarchy javax.swing.JPasswordField$AccessibleJPasswordField))
;;=> (java.lang.Object
;; javax.accessibility.AccessibleContext
;; java.awt.Component$AccessibleAWTComponent
;; java.awt.Container$AccessibleAWTContainer
;; javax.swing.JComponent$AccessibleJComponent
;; javax.swing.text.JTextComponent$AccessibleJTextComponent
;; javax.swing.JTextField$AccessibleJTextField
;; javax.swing.JPasswordField$AccessibleJPasswordField)
(require '(clojure [reflect :as cr] [pprint :as pp]))
;; Let us see what is available in the DynamicClassLoader
(->> clojure.lang.DynamicClassLoader
cr/type-reflect
:members
(sort-by :name)
(pp/print-table [:name :flags :parameter-types]))
;| :name | :flags | :parameter-types |
;|---------------------------------+-----------------------------+--------------------------------------------|
;| EMPTY_URLS | #{:static :final} | |
;| addURL | #{:public} | [java.net.URL] |
;| classCache | #{:static} | |
;| clojure.lang.DynamicClassLoader | #{:public} | [java.lang.ClassLoader] |
;| clojure.lang.DynamicClassLoader | #{:public} | [] |
;| constantVals | #{} | |
;| defineClass | #{:public} | [java.lang.String byte<> java.lang.Object] |
;| findClass | #{:protected} | [java.lang.String] |
;| findInMemoryClass | #{:static} | [java.lang.String] |
;| getConstants | #{:public} | [int] |
;| loadClass | #{:synchronized :protected} | [java.lang.String boolean] |
;| registerConstants | #{:public} | [int java.lang.Object<>] |
;| rq | #{:static :final} | |