Some simplified examples of how to read Java and turn it into Clojure. Intended for Clojurists without a background in Java. Based on clojure.org's Java Interop reference.
Consider reading: https://stackoverflow.com/questions/11993077/difference-between-static-methods-and-instance-methods
Say we come across some Java that calls a method on a string literal:
String s = "fred";
System.out.println(s.toUpperCase());
-> "FRED"
This is called invoking an instance member (toUpperCase
) of an instance (s
) of a class (String
). We can look up the Javadoc and see that toUpperCase is listed as a Method that is called on a String and which returns a String.
Because we're calling a method of the String class on an instance of a String, we use the instance member macro to implement the same call in Clojure. The syntax is: (.instanceMember instance args*)
For example:
(.toUpperCase "fred")
-> "FRED"
We can use the same syntax when invoking an instance member of a class name: (.instanceMember Classname args*)
For example, we can get the name of the String class name itself, with getName:
String.class.getName()
-> "java.lang.String"
In Clojure:
(.getName String)
-> "java.lang.String"
Sometimes we'll come across Java that calls a method directly from the class, instead of on an instance of that class. For instance, the getProperty method of System is listed as a static method, so in Java, it is called directly on the System class:
System.getProperty("java.vm.version");
-> "1.6.0_07-b06-57"
Notice how getProperty
has "static" under the "Modifier" column of the Javadoc's Method Summary, and its Method Detail lists it as public static String getProperty(String key)
. Because it is static, getProperty
belongs to the System class itself, not to an instance of the System class. This means it is called from System itself rather than from a System object we create.
The Clojure translation of calling static methods uses slash syntax: (Classname/staticMethod args*)
, which makes the difference from calling instance members more obvious:
(System/getProperty "java.vm.version")
-> "1.6.0_07-b06-57"
Sometimes--though not often--Java objects allow you to directly read the values of their member fields. (More often, you're forced to use a "getter" method to read the value.) For instance we can get the x
value of a Point object using Java:
Point p = new Point(4,6);
p.x;
-> 4
The Javadoc tells us that x
is a Field of Point, rather than a Method such as getX
. This is also hinted by the fact that p.x
ends with no parentheses.
The Clojure syntax for an instance field is a dot-dash: (.-instanceField instance)
(In Clojure's Java interop, a dash prefix indicates field access.) So the above Java translated to Clojure looks like:
(.-x (java.awt.Point. 4 6))
-> 4
(Notice that we omit the comma, because commas are optional whitespace in Clojure. Most folks only include them to mark pairs in hard-to-read maps.)
Finally, we might need to read the value of a class's field. These are called static fields. For instance, we get the value of Pi directly from the Math class, without creating an object of class Math:
Math.PI
-> 3.141592653589793
The Clojure syntax for this is Classname/staticField, so translating the Pi example above is:
Math/PI
-> 3.141592653589793