Browse Learn Clojure Foundations as a Java Developer

Java Objects at Interop Boundaries

Create, configure, and expose Java objects from Clojure without letting object construction leak into the functional core; compare constructors, doto, proxy, reify, and gen-class at the boundary.

Sometimes you need a Java object: a client, a builder, a stream, a time type, a JDBC datasource. In idiomatic Clojure, you create and configure Java objects at the edges, then keep the core of your program working with plain data.

Two patterns show up a lot:

  • Constructor calls like (java.util.ArrayList. 10) or (java.io.File. "x.txt")
  • doto for “configure this object and return it”

The aim is to keep object creation localized so it does not leak across your codebase as an implicit global dependency.

In this section

  • The proxy Macro for Java Interfaces
    Use Clojure's proxy macro when Java APIs require an anonymous class that extends a class or implements interfaces, and learn where it is heavier than reify.
  • The reify Form for Java Interfaces
    Use reify to create inline implementations of Java interfaces or Clojure protocols, especially when a callback or adapter object should stay local to one call site.
  • The gen-class Tool for Java Classes
    Generate named Java-visible classes from Clojure only when Java code, framework entry points, or ahead-of-time compilation requirements make an anonymous object insufficient.
Revised on Saturday, May 23, 2026