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) 5.2 user=> Math/PI 3.141592653589793
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 java.lang.Math user=> (class Math) java.lang.Class 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")