Skip to content

Instantly share code, notes, and snippets.

@daveliepmann
Last active April 26, 2021 03:03
Show Gist options
  • Save daveliepmann/86996c8b9842d78b0509ca24ad4a92e9 to your computer and use it in GitHub Desktop.
Save daveliepmann/86996c8b9842d78b0509ca24ad4a92e9 to your computer and use it in GitHub Desktop.
Java interop for the Clojurists who haven't done Java and who need to translate Java code to Clojure

Converting Java to Clojure for Non-Java Folks

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

Calling methods of an instance

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"

Calling methods of a class

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"

Accessing fields of a class instance

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.)

Accessing fields of a class

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment