Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get the methods of a Java class from Clojure?

Tags:

clojure

How can I get the methods of a Java class from Clojure?

like image 965
yazz.com Avatar asked Apr 28 '11 15:04

yazz.com


People also ask

Can clojure use Java libraries?

Clojure programs get compiled to Java bytecode and executed within a JVM process. Clojure programs also have access to Java libraries, and you can easily interact with them using Clojure's interop facilities.

Is clojure interoperable with Java?

Overview. Clojure was designed to be a hosted language that directly interoperates with its host platform (JVM, CLR and so on). Clojure code is compiled to JVM bytecode. For method calls on Java objects, Clojure compiler will try to emit the same bytecode javac would produce.

How do you call a method class?

To call a class method, put the class as the first argument. Class methods can be can be called from instances and from the class itself. All of these use the same method. The method can use the classes variables and methods.


4 Answers

[EDIT 2]

Per M Smith's comment below, this accomplishes the same but provides sorting by method name and only returns methods:

(print-table   (sort-by :name      (filter :exception-types (:members (r/reflect "foo"))))) 

[/EDIT 2]

[EDIT]

My original answer refers to Clojure 1.2, but things have changed with Clojure 1.3. This works without any reliance on Clojure's contrib libraries now:

(require '[clojure.reflect :as r]) (use '[clojure.pprint :only [print-table]])  (print-table (:members (r/reflect "foo"))) 

This provides a much more decoupled approach, with the reflect function providing all kinds of information on the argument passed in (in this case, a String "foo") and the print-table function taking any generic tabular data structure and pretty printing it as such.

This is originally from this thread on the Google Group.

[/EDIT]

I'd use the show function in the clojure.contrib.repl-utils namespace, which will print all static and instance members for an object (or class of an object). I require it like so:

(require '[clojure.contrib.repl-utils :as ru]) 

Here's an example using Joda Time:

(import 'org.joda.time.DateTime) (ru/show DateTime) (ru/show (DateTime.)) 

The first example demonstrates how you can simply pass a class to show, while the second demonstrates that you can pass an instance of the class as well.

This of course works for lots of Clojure items that are Java classes underneath. Here's an example of seeing all methods available to an instance of java.lang.String:

(ru/show "foo") 
like image 103
semperos Avatar answered Sep 21 '22 23:09

semperos


Try clojure.reflect, available in recent Clojure 1.3.0-alpha* releases. It returns Clojure data structures that you can search/filter as needed.

Clojure 1.3.0-alpha6 user=> (use 'clojure.reflect 'clojure.pprint) nil user=> (pprint (reflect "hello")) {:bases  #{java.io.Serializable java.lang.Comparable java.lang.Object    java.lang.CharSequence},  :flags #{:public :final},  :members  #{{:name valueOf,     :return-type java.lang.String,     :declaring-class java.lang.String,     :parameter-types [boolean],     :exception-types [],     :flags #{:static :public}} ... 
like image 39
Stuart Sierra Avatar answered Sep 19 '22 23:09

Stuart Sierra


You can use this method that uses clojure.reflect and extends the previous answers:

(use 'clojure.reflect)

(defn all-methods [x]
    (->> x reflect 
           :members 
           (filter :return-type)  
           (map :name) 
           sort 
           (map #(str "." %) )
           distinct
           println))

Usage:

 (all-methods "")
 ; => (.charAt .checkBounds .codePointAt .codePointBefore .codePointCount .compareTo .compareToIgnoreCase .concat .contains .contentEquals .copyValueOf .endsWith .equals .equalsIgnoreCase .format .getBytes .getChars .hashCode .indexOf .intern .isEmpty .lastIndexOf .length .matches .offsetByCodePoints .regionMatches .replace .replaceAll .replaceFirst .split .startsWith .subSequence .substring .toCharArray .toLowerCase .toString .toUpperCase .trim .valueOf)

 (all-methods 1)
 ; => (.bitCount .byteValue .compareTo .decode .doubleValue .equals .floatValue .getChars .getLong .hashCode .highestOneBit .intValue .longValue .lowestOneBit .numberOfLeadingZeros .numberOfTrailingZeros .parseLong .reverse .reverseBytes .rotateLeft .rotateRight .shortValue .signum .stringSize .toBinaryString .toHexString .toOctalString .toString .toUnsignedString .valueOf)

 (all-methods java.util.StringTokenizer)
 ; => (.countTokens .hasMoreElements .hasMoreTokens .isDelimiter .nextElement .nextToken .scanToken .setMaxDelimCodePoint .skipDelimiters)
like image 42
zcaudate Avatar answered Sep 19 '22 23:09

zcaudate


This code will print all public methods, both declared and inherited.

(doseq [m (.getMethods (type "Hello"))]
  (println "Method Name: " (.getName m))
  (println "Return Type: " (.getReturnType m) "\n"))
like image 21
dbyrne Avatar answered Sep 18 '22 23:09

dbyrne