Pure Danger Tech


Learning Clojure #16: class reference

08 Aug 2010

Most new Clojure devs find the need to call static Java methods or access static Java fields pretty quickly and doing so is easy:

user=> (Math/max 5.2 2.7)
user=> Math/PI

But recently I need to get the Class of a well-known Java class, which I would normally have done with String.class in Java. This *looks* like a static field so I first tried to access it like one:

user=> String/class
#<CompilerException java.lang.Exception: Unable to find static field: class in class java.lang.String (NO_SOURCE_FILE:405)>

No dice. This makes sense when you consider that saying Foo.class is not really referencing a field, but rather a part of the Java language syntax (just like this.) defined as “class literals” in JLS 15.8.2.

Eventually it occurred to me that if (Foo/method) is a static method call and Foo/field yields the value of a static field then maybe just Foo is the class reference. Sure enough, it is! So if you are calling an API that requires a Class, you can just pass the name of the class to refer to the class of that type.

user=> Math
user=> (class Math)
user=> (seq (.getFields Math))
(#<Field public static final double java.lang.Math.E> #<Field public static final double java.lang.Math.PI>)

It’s sometimes helpful when working with Java objects to use bean to get a handy map view into the Java object:

user=> (map #(:name (bean %)) (seq (:fields (bean Math))))
("E" "PI")