Clojure
Share your thoughts in the 2024 State of Clojure Survey!

Java Interop

Class access

Classname
Classname$InnerClass
Classname/N
primitive/N

Symbols representing class names are resolved to the Class instance. Inner or nested classes are separated from their outer class with a $. Fully-qualified class names are always valid. If a class is `import`ed in the namespace, it may be used without qualification. All classes in java.lang are automatically imported to every namespace.

A symbol whose ns-part names a class or a primitive, and whose name part is a single digit between 1 and 9, designates an array class of that component type and dimension. Added in 1.12.

String
-> java.lang.String
(defn date? [d] (instance? java.util.Date d))
-> #'user/date?
(.getEnclosingClass java.util.Map$Entry)
-> java.util.Map
(.getComponentType String/1)
-> java.lang.String

Member access

(.instanceMember instance args*)
(.instanceMember Classname args*)
(.-instanceField instance)
(Classname/staticMethod args*)
(Classname/.instanceMethod instance args*)
Classname/staticField

(.toUpperCase "fred")
-> "FRED"
(.getName String)
-> "java.lang.String"
(.-x (java.awt.Point. 1 2))
-> 1
(System/getProperty "java.vm.version")
-> "1.6.0_07-b06-57"
Math/PI
-> 3.141592653589793

The preferred idiomatic forms for accessing field or method members are given above. The instanceMember form works for both fields and methods. The instanceField form is required if both a field and a 0-argument method of the same name exist.

Since Clojure 1.12, Classname/.instanceMethod refers to an instance method. When an instance method is specified, the instance should be provided after the member and before the args. When a qualified instance method is present then the qualifying class takes precedence over any additional type information on the instance for the purpose of resolving the instance method.

The unqualified "." forms expand into calls to the dot operator (described below) at macroexpansion time. The expansions are as follows:

(.instanceMember instance args*) ==> (. instance instanceMember args*)
(.instanceMember Classname args*) ==> (. (identity Classname) instanceMember args*)
(.-instanceField instance) ==> (. instance -instanceField)

Method values

Since Clojure 1.12, programmers can use qualified methods as ordinary functions in value contexts - the compiler will automatically generate the wrapping function. When used as values, qualified methods supply only the class and method name, and thus cannot resolve overloaded methods. Therefore, the compiler will generate a reflective call when a qualified method does not resolve due to overloading. Developers can supply :param-tags metadata on qualified methods to specify the signature of a single desired method, 'resolving' it. :param-tags are ignored on unqualified methods like .instanceMember.

The Dot special form

(. instance-expr member-symbol)
(. Classname-symbol member-symbol)
(. instance-expr -field-symbol)
(. instance-expr (method-symbol args*)) or (. instance-expr method-symbol args*)
(. Classname-symbol (method-symbol args*)) or (. Classname-symbol method-symbol args*)

Special form.

The '.' special form is the basis for access to Java. It can be considered a member-access operator, and/or read as 'in the scope of'.

If the first operand is a symbol that resolves to a class name, the access is considered to be to a static member of the named class. Note that nested classes are named EnclosingClass$NestedClass, per the JVM spec. Otherwise it is presumed to be an instance member and the first argument is evaluated to produce the target object.

For the special case of invoking an instance member on a Class instance, the first argument must be an expression that evaluates to the class instance - note that the preferred form at the top expands Classname to (identity Classname).

If the second operand is a symbol and no args are supplied it is taken to be a field access - the name of the field is the name of the symbol, and the value of the expression is the value of the field, unless there is a no argument public method of the same name, in which case it resolves to a call to the method. If the second operand is a symbol starting with -, the member-symbol will resolve only as field access (never as a 0-arity method) and should be preferred when that is the intent.

If the second operand is a list, or args are supplied, it is taken to be a method call. The first element of the list must be a simple symbol, and the name of the method is the name of the symbol. The args, if any, are evaluated from left to right, and passed to the matching method, which is called, and its value returned. If the method has a void return type, the value of the expression will be nil. Note that placing the method name in a list with any args is optional in the canonic form, but can be useful to gather args in macros built upon the form.

Note that boolean return values will be turned into Booleans, chars will become Characters, and numeric primitives will become Numbers unless they are immediately consumed by a method taking a primitive.

The member access forms given at the top of this section are preferred for use in all cases other than in macros.


(.. instance-expr member+)
(.. Classname-symbol member+)

member ⇒ fieldName-symbol or (instanceMethodName-symbol args*)

Macro. Expands into a member access (.) of the first member on the first argument, followed by the next member on the result, etc. For instance:

(.. System (getProperties) (get "os.name"))

expands to:

(. (. System (getProperties)) (get "os.name"))

but is easier to write, read, and understand. See also the -> macro which can be used similarly:

(-> (System/getProperties) (.get "os.name"))


(doto instance-expr (instanceMethodName-symbol args*)*)

Macro. Evaluates instance-expr then calls all of the methods/functions with the supplied arguments in succession on the resulting object, returning it.

(doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2))
-> {a=1, b=2}

(Classname. args*)
(Classname/new args*)
(new Classname args*)

Special form.

The args, if any, are evaluated from left to right, and passed to the constructor of the class named by Classname. The constructed object is returned.

As shown, in addition to the canonic special form new, Clojure supports special macroexpansion of symbols containing '.':

(new Classname args*)

can be written

(Classname. args*) ;note trailing dot

the latter expanding into (new Classname args) syntax at macro expansion time.

Since Clojure 1.12, a qualified form may also be used (it is not rewritten at macro expansion time):

(Classname/new args*)

Like methods, qualified constructors Classname/new can be used in value contexts and take :param-tags metadata.


(instance? Class expr)

Evaluates expr and tests if it is an instance of the class. Returns true or false


(set! (. instance-expr instanceFieldName-symbol) expr)
(set! (. Classname-symbol staticFieldName-symbol) expr)

Assignment special form.

When the first operand is a field member access form, the assignment is to the corresponding field. If it is an instance field, the instance expr will be evaluated, then the expr.

In all cases the value of expr is returned.

Note - you cannot assign to function params or local bindings. Only Java fields, Vars, Refs and Agents are mutable in Clojure.


(memfn method-name arg-names*)

Macro. Expands into code that creates a fn that expects to be passed an object and any args and calls the named instance method on the object passing the args. Use when you want to treat a Java method as a first-class fn.

(map (memfn charAt i) ["fred" "ethel" "lucy"] [1 2 3])
-> (\r \h \y)

Note it is almost always preferable to do this directly now, with syntax like:

(map #(.charAt %1 %2) ["fred" "ethel" "lucy"] [1 2 3])
-> (\r \h \y)

(bean obj)

Takes a Java object and returns a read-only implementation of the map abstraction based upon its JavaBean properties.

(bean java.awt.Color/black)
-> {:RGB -16777216, :alpha 255, :blue 0, :class java.awt.Color,
    :colorSpace #object[java.awt.color.ICC_ColorSpace 0x5cb42b "java.awt.color.ICC_ColorSpace@5cb42b"],
    :green 0, :red 0, :transparency 1}

Support for Java in Clojure Library Functions

Many of the Clojure library functions have defined semantics for objects of Java types. contains? and get work on Java Maps, arrays, Strings, the latter two with integer keys. count works on Java Strings, Collections and arrays. nth works on Java Strings, Lists and arrays. seq works on Java reference arrays, Iterables and Strings. Since much of the rest of the library is built upon these functions, there is great support for using Java objects in Clojure algorithms.

Implementing Interfaces and Extending Classes

Clojure supports the dynamic creation of objects that implement one or more interfaces and/or extend a class with the proxy macro. The resulting objects are of an anonymous class. You can also generate statically-named classes and .class files with gen-class. As of Clojure 1.2, reify is also available for implementing interfaces.

Java annotations may be attached to classes, constructors, and methods via metadata on gen-class and Clojure type constructs, see the datatypes reference for an example.


(proxy [class-and-interfaces] [args] fs+)

class-and-interfaces - a vector of class names
args - a (possibly empty) vector of arguments to the superclass constructor.
f ⇒ (name [params*] body) or (name ([params*] body) ([params+] body) …​)

Macro

Expands to code which creates a instance of a proxy class that implements the named class/interface(s) by calling the supplied fns. A single class, if provided, must be first. If not provided it defaults to Object. The interfaces names must be valid interface types. If a method fn is not provided for a class method, the superclass method will be called. If a method fn is not provided for an interface method, an UnsupportedOperationException will be thrown should it be called. Method fns are closures and can capture the environment in which proxy is called. Each method fn takes an additional implicit first arg, which is bound to this. Note that while method fns can be provided to override protected methods, they have no other access to protected members, nor to super, as these capabilities cannot be proxied.

Arrays

Clojure supports the creation, reading and modification of Java arrays. It is recommended that you limit use of arrays to interop with Java libraries that require them as arguments or use them as return values.

Note that many other Clojure functions work with arrays such as via the seq library. The functions listed here exist for initial creation of arrays, or to support mutation or higher performance operations on arrays.

Vararg methods

Java vararg methods treat the trailing varargs parameter as an array. They can be invoked from Clojure by passing an explicit array in place of the vargs.

Depending on the varargs type, use the type-specific array constructors for primitives or into-array to make an array of a specific type. See the FAQ for examples.

Create array from existing collection: aclone amap to-array to-array-2d into-array
Multi-dimensional array support: aget aset to-array-2d make-array
Type-specific array constructors: boolean-array byte-array char-array double-array float-array int-array long-array object-array short-array
Primitive array casts: booleans bytes chars doubles floats ints longs shorts
Mutate an array: aset
Process an existing array: aget alength amap areduce

Type Hints

Clojure supports the use of type hints to assist the compiler in avoiding reflection in performance-critical areas of code. Normally, one should avoid the use of type hints until there is a known performance bottleneck. Type hints are metadata tags placed on symbols or expressions that are consumed by the compiler. They can be placed on function parameters, let-bound names, var names (when defined), and expressions:

(defn len [x]
  (.length x))

(defn len2 [^String x]
  (.length x))

user=> (time (reduce + (map len (repeat 1000000 "asdf"))))
"Elapsed time: 3007.198 msecs"
4000000
user=> (time (reduce + (map len2 (repeat 1000000 "asdf"))))
"Elapsed time: 308.045 msecs"
4000000

Once a type hint has been placed on an identifier or expression, the compiler will try to resolve any calls to methods thereupon at compile time. In addition, the compiler will track the use of any return values and infer types for their use and so on, so very few hints are needed to get a fully compile-time resolved series of calls. Note that type hints are not needed for static fields or the return values of static methods as the compiler always has that type information.

There is a *warn-on-reflection* flag (defaults to false) which will cause the compiler to warn you when it can’t resolve to a direct call:

(set! *warn-on-reflection* true)
-> true

(defn foo [s] (.charAt s 1))
-> Reflection warning, line: 2 - call to charAt can't be resolved.
-> #user/foo

(defn foo [^String s] (.charAt s 1))
-> #user/foo

For function return values, the type hint can be placed before the parameter vector:

(defn hinted-single ^String [])

-> #user/hinted-single

(defn hinted
  (^String [])
  (^Integer [a])
  (^java.util.List [a & args]))

-> #user/hinted

Aliases

Clojure provides aliases for primitive Java types and arrays which do not have typical representations as Java class names. The types are represented according to the specification of Java Field Descriptors. For example, byte arrays (byte-array []) have a type of "[B".

  • int - A primitive int

  • ints - An int array

  • long - A primitive long

  • longs - A long array

  • float - A primitive float

  • floats - A float array

  • double - A primitive double

  • doubles - A double array

  • void - A void return

  • short - A primitive short

  • shorts - A short array

  • boolean - A primitive boolean

  • booleans - A boolean array

  • byte - A primitive byte

  • bytes - A byte array

  • char - A primitive character

  • chars - A character array

  • objects - An object array

param-tags

Since Clojure 1.12, developers can supply :param-tags metadata on qualified methods to specify the signature of a single desired method, 'resolving' it. The :param-tags metadata is a vector of zero or more tags: […​ tag …​]. A tag is any existing valid :tag metadata value as described above. Each tag corresponds to a parameter in the desired signature (arity should match the number of tags). Parameters with non-overloaded types can use the placeholder _ in lieu of the tag. When you supply :param-tags metadata on a qualified method, the metadata must allow the compiler to resolve it to a single method at compile time.

A new metadata reader syntax ^[ …​ ] attaches :param-tags metadata to member symbols, just as ^tag attaches :tag metadata to a symbol.

Support for Java Primitives

Clojure has support for high-performance manipulation of, and arithmetic involving, Java primitive types in local contexts. All Java primitive types are supported: int, float, long, double, boolean, char, short, and byte.

  • let/loop-bound locals can be of primitive types, having the inferred, possibly primitive type of their init-form.

  • recur forms that rebind primitive locals do so without boxing, and do type-checking for same primitive type.

  • Arithmetic (+,-,*,/,inc,dec,<,<=,>,>= etc) is overloaded for primitive types where semantics are same.

  • aget / aset are overloaded for arrays of primitives

  • aclone, alength functions for arrays of primitives

  • constructor functions for primitive arrays: float-array, int-array, etc.

  • Type hints for primitive arrays - ^ints, ^floats, etc.

  • Coercion ops int, float, etc. produce primitives when consumer can take primitive

  • The num coercion function boxes primitives to force generic arithmetic

  • Array cast functions ints longs, etc. which produce int[], long[], etc.

  • A set of "unchecked" operations for utmost performing, but potentially unsafe, integer (int/long) ops: unchecked-multiply unchecked-dec unchecked-inc unchecked-negate unchecked-add unchecked-subtract unchecked-remainder unchecked-divide

  • A dynamic var to automatically swap safe operations with unchecked operations: *unchecked-math*

  • amap and areduce macros for functionally (i.e. non-destructively) processing one or more arrays in order to produce a new array or aggregate value respectively.

Rather than write this Java:

static public float asum(float[] xs){
  float ret = 0;
  for(int i = 0; i < xs.length; i++)
    ret += xs[i];
  return ret;
}

you can write this Clojure:

(defn asum [^floats xs]
  (areduce xs i ret (float 0)
    (+ ret (aget xs i))))

and the resulting code is exactly the same speed (when run with java -server).

The best aspect of this is that you need not do anything special in your initial coding. Quite often these optimizations are unneeded. Should a bit of code be a bottleneck, you can speed it up with minor adornment:

(defn foo [n]
  (loop [i 0]
    (if (< i n)
      (recur (inc i))
      i)))

(time (foo 100000))
"Elapsed time: 0.391 msecs"
100000

(defn foo2 [n]
  (let [n (int n)]
    (loop [i (int 0)]
      (if (< i n)
        (recur (inc i))
        i))))

(time (foo2 100000))
"Elapsed time: 0.084 msecs"
100000

Functions have limited support for primitive arguments and return type: type hints for long and double (only these) generate primitive-typed overloads. Note that this capability is restricted to functions of arity no greater than 4.

Thus a function defined as

(defn foo ^long [^long n])

both takes and returns values of primitive type long (invocations with a boxed argument and indeed any object result in a cast and delegation to the primitive-typed overload).

Coercions

Primitive coercions

At times it is necessary to have a value of a particular primitive type. These coercion functions yield a value of the indicated type as long as such a coercion is possible: bigdec bigint boolean byte char double float int long num short

Functional Interface Conversion

Java programs emulate functions with Functional Interfaces, which have a single method.

Clojure developers can invoke Java methods taking Functional Interfaces by passing functions with matching arity. The Clojure compiler implicitly converts functions to the required Functional Interface by constructing a lambda adapter. You can explicitly coerce a function to a Functional Interface by hinting the binding name in a let binding, e.g. to avoid repeated adapter construction in a loop, e.g. (let [^java.util.function.Predicate p even?] …​).

Since Clojure 1.12, all IDeref impls (delay, future, atom, etc) implement the Supplier interface directly.

Some optimization tips

  • All arguments are passed to Clojure fns as objects, so there’s no point to putting arbitrary primitive type hints on fn args (excepting primitive array type hints, and long and double as noted). Instead, use the let technique shown to place args in primitive locals if they need to participate in primitive arithmetic in the body.

  • (let [foo (int bar)] …​) is the correct way to get a primitive local. Do not use ^Integer etc.

  • Don’t rush to unchecked math unless you want truncating operations. HotSpot does a good job at optimizing the overflow check, which will yield an exception instead of silent truncation. On a typical example, that has about a 5% difference in speed - well worth it. Also, people reading your code don’t know if you are using unchecked for truncation or performance - best to reserve it for the former and comment if the latter.

  • There’s usually no point in trying to optimize an outer loop, in fact it can hurt you as you’ll be representing things as primitives which just have to be re-boxed in order to become args to the inner call. The only exception is reflection warnings - you must get rid of them in any code that gets called frequently.

  • Almost every time someone presents something they are trying to optimize with hints, the faster version has far fewer hints than the original. If a hint doesn’t improve things in the end - take it out.

  • Many people seem to presume only the unchecked- ops do primitive arithmetic - not so. When the args are primitive locals, regular + and * etc do primitive math with an overflow check - fast and safe.

  • So, the simplest route to fast math is to leave the operators alone and just make sure the source literals and locals are primitive. Arithmetic on primitives yields primitives. If you’ve got a loop (which you probably do if you need to optimize) make sure the loop locals are primitives first - then if you accidentally are producing a boxed intermediate result you’ll get an error on recur. Don’t solve that error by coercing your intermediate result, instead, figure out what argument or local is not primitive.

Java Stream Support

Clojure collections implement the Java collection interfaces, which provide Stream and Spliterator access. Clojure persistent vectors implement a custom Spliterator that supports parallel streams.

Clojure provides functions (since 1.12) to interoperate with streams in an idiomatic manner, all functions behave analogously to their Clojure counterparts:

All of these operations are terminal stream operations (they consume the stream).

Simple XML Support

Included with the distribution is simple XML support, found in the src/clj/clojure/xml.clj file. All names from this file are in the clojure.xml namespace.


(parse source)

Parses and loads the source, which can be a File, InputStream or String naming a URI. Returns a tree of the clojure.xml/element struct-map, which has the keys :tag, :attrs, and :content. and accessor fns tag, attrs, and content.

(clojure.xml/parse "/Users/rich/dev/clojure/build.xml")
-> {:tag :project, :attrs {:name "clojure", :default "jar"}, :content [{:tag :description, ...

Calling Clojure From Java

The clojure.java.api package provides a minimal interface to bootstrap Clojure access from other JVM languages. It does this by providing:

  1. The ability to use Clojure’s namespaces to locate an arbitrary var, returning the var’s clojure.lang.IFn interface.

  2. A convenience method read for reading data using Clojure’s edn reader

IFns provide complete access to Clojure’s APIs. You can also access any other library written in Clojure, after adding either its source or compiled form to the classpath.

The public Java API for Clojure consists of the following classes and interfaces:

All other Java classes should be treated as implementation details, and applications should avoid relying on them.

To lookup and call a Clojure function:

IFn plus = Clojure.var("clojure.core", "+");
plus.invoke(1, 2);

Functions in clojure.core are automatically loaded. Other namespaces can be loaded via require:

IFn require = Clojure.var("clojure.core", "require");
require.invoke(Clojure.read("clojure.set"));

IFns can be passed to higher order functions, e.g. the example below passes inc to map:

IFn map = Clojure.var("clojure.core", "map");
IFn inc = Clojure.var("clojure.core", "inc");
map.invoke(inc, Clojure.read("[1 2 3]"));

Most IFns in Clojure refer to functions. A few, however, refer to non-function data values. To access these, use deref instead of invoking the function:

IFn printLength = Clojure.var("clojure.core", "*print-length*");
IFn deref = Clojure.var("clojure.core", "deref");
deref.invoke(printLength);