Skip to content

Clojure Java Interop Guide — Calling Java From Clojure and Using Libraries

DodaTech Updated 2026-06-28 2 min read

In this tutorial, you will learn about Clojure Java Interop Guide. We cover key concepts, practical examples, and best practices to help you master this topic.

Clojure Java interop provides direct access to Java classes and methods -- . for method calls, new with ClassName. for constructors, doto for fluent chaining, import for class resolution, and gen-class for creating Java-compatible classes from Clojure.

Basic Interop

;; Constructing objects
(String. "hello")
(java.util.Date.)
(java.io.File. "/tmp/test.txt")

;; Calling methods
(.toUpperCase "hello")           ;; "HELLO"
(.contains "hello" "ll")         ;; true
(.length (java.io.File. "/tmp"))

;; Static methods
(Math/sqrt 16)          ;; 4.0
(System/getProperty "java.version")
(Integer/parseInt "42")

Property Access

;; Field access (getter)
(.name (java.io.File. "/tmp/test.txt"))  ;; "test.txt"
(.path (java.io.File. "/tmp"))           ;; "/tmp"

;; Field setting
(let [buf (java.io.StringWriter.)]
  (set! (.lock buf) nil)
  buf)

;; Instance? check
(instance? String "hello")       ;; true
(instance? Number 42)            ;; true

Doto Chaining

;; doto: call multiple methods on the same object
(let [arrlist (java.util.ArrayList.)]
  (doto arrlist
    (.add "first")
    (.add "second")
    (.add "third"))
  (.size arrlist))  ;; 3

;; Configure a GUI component
(doto (javax.swing.JFrame.)
  (.setTitle "My App")
  (.setSize 800 600)
  (.setVisible true))

Implementing Interfaces

;; Proxy: create anonymous implementation
(def my-runner
  (proxy [java.lang.Runnable] []
    (run []
      (println "Running in proxy"))))

(.run my-runner)

;; reify: simpler, preferred for Clojure interfaces
(def my-comp
  (reify java.util.Comparator
    (compare [this a b]
      (- (.length a) (.length b)))))

(.compare my-comp "short" "longest")  ;; -3

Gen-Class

;; Generate a Java class from Clojure
(ns my-app.java-class
  (:gen-class
    :name my_app.Calculator
    :methods [[add [int int] int]
              [multiply [int int] int]]))

(defn -add [this a b]
  (+ a b))

(defn -multiply [this a b]
  (* a b))

;; Compile to .class file
;; (lein compile) or (cider-load-all)

Common Mistakes

1. Forgetting import

Use (import 'java.util.Date) or (:import [java.util Date]) in ns. Fully qualified names are verbose.

2. Method signatures

Overloaded Java methods need matching argument types. Use type hints: ^String, ^Integer.

3. Null handling

Clojure nil maps to Java null. Java methods returning null become nil. Use (.someMethod) cautiously.

Practice Questions

1. How do you call a Java method? (.methodName object args...) or (.methodName Classname/staticMethod args).

2. How do you create a Java object? (ClassName. args). The dot after the class name calls the constructor.

3. How do you implement a Java interface? Use reify for simple cases: (reify SomeInterface (method [this] ...)).

FAQ

{{< faq question="How do I type hint in Clojure?" >}} (defn len [^String s] (.length s)). Type hints avoid Reflection and improve performance.

{{< /faq >}}

{{< faq question="Can I extend Java classes?" >}} Yes. Use (extend java.util.Date MyProtocol {:method ...}) for protocols, or gen-class for new classes.

{{< /faq >}}

{{< faq question="What is reflection warning?" >}} Warning when Clojure can't determine the Java method at compile time. Add type hints to suppress.

{{< /faq >}}

What's Next

Now learn about EDN format.

Topic Description Link
EDN Extensible Data Notation {{< ref "15-edn" >}}
Web Development Web dev in Clojure {{< ref "16-web" >}}

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro