Tech behind Tech

Raw information. No finesse :)

Calling java from Clojure

leave a comment »


 

Importing Java Class

In repl, when you want to import one Java class you can do

(import 'java.util.Date)

When you want to import more Java classes from a same package you can do

(import [java.util Date HashMap])
(ns com.techbehindtech.java
        (:import [java.util Date HashMap]))

Creating Instances

(import 'java.util.Date)

(def today (new Date))

;; or

(def today (Date.))

Calling Java instance methods

user> (import 'java.util.Date)
java.util.Date
user> (let [today (Date.)]
        (.getTime today))
1286749020847

Calling Java static methods

user> (System/currentTimeMillis)
1286847946813

Sugar sytax:

Doto:

You want to write a function that will return UTC Java Calendar object set at a specific time.

user> (import [java.util Calendar TimeZone Date])
user> (defn utc-time [d]
        (let [cal (Calendar/getInstance)]
              (.setTimeZone cal (TimeZone/getTimeZone "UTC"))
              (.setTime cal d)
          cal))

#'user/utc-time

The let block is ugly. We could use doto to make this code better.

user> (import [java.util Calendar TimeZone Date])	
user> (defn utc-time [d]        
         (doto (Calendar/getInstance)
              (.setTimeZone (TimeZone/getTimeZone "UTC"))
              (.setTime d)))

#'user/utc-time
	

Dot Dot:

Sometimes in java you want to make calls in chain

Bad way

user> (.length (.getProperty (System/getProperties) "user.country"))
2
	

Better way

user> (. (. (System/getProperties) getProperty "user.country") length)
2

Even Better

user> (..
       (System/getProperties)
       (getProperty "user.country")
       (length))
2

Avoiding Reflection

By default jvm will be using reflection to identify type. Reflection is slow. But we can give type hints that way jvm does not have to use reflection. For example we can rewrite utc-time with type-hints like this

user> (set! *warn-on-reflection* true)
true
user> (defn str-length [s] (.length s))
Reflection warning, NO_SOURCE_FILE:1 - reference to field length can't be resolved.
#'user/str-length
user> (defn str-length [#^String s] (.length s))
#'user/str-length
	

Implementing interfaces and extending classes

Let us implement Java Runnable interface

user> (proxy [Runnable] []
        (run []
             (println "running ...")))
#<Object$Runnable$36fc6471 user.proxy$java.lang.Object$Runnable$36fc6471@6dd33544>

In clojure 1.2, you could use reify macro to implement. In fact it is better than using proxy.

user> (reify Runnable
             (run [this]
                  (println "running ...")))
#<user$eval1664$reify__1665 user$eval1664$reify__1665@574f7121>

Written by Siva Jagadeesan

October 11, 2010 at 10:43 pm

Posted in Clojure

Tagged with , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 146 other followers

%d bloggers like this: