You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: articles/language/interop/index.html
+19-5Lines changed: 19 additions & 5 deletions
Original file line number
Diff line number
Diff line change
@@ -61,7 +61,7 @@
61
61
<divid="page-header">
62
62
<h2>Language: Java Interop</h2>
63
63
</div>
64
-
<olclass="toc"><li><ahref="#what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</a></li><li><ahref="#overview">Overview</a></li><li><ahref="#imports">Imports</a></li><ol><li><ahref="#automatic-imports-for-javalang">Automatic Imports For java.lang.*</a></li><li><ahref="#inner-nested-classes">Inner (Nested) Classes</a></li></ol><li><ahref="#how-to-instantiate-java-classes">How to Instantiate Java Classes</a></li><li><ahref="#how-to-invoke-java-methods">How to Invoke Java Methods</a></li><ol><li><ahref="#instance-methods">Instance Methods</a></li><li><ahref="#static-methods">Static Methods</a></li><li><ahref="#chained-calls-with-the-double-dot-form">Chained Calls With The Double Dot Form</a></li><li><ahref="#multiple-calls-on-the-same-object">Multiple Calls On the Same Object</a></li></ol><li><ahref="#how-to-access-java-fields">How to Access Java Fields</a></li><li><ahref="#how-to-set-java-fields">How to Set Java Fields</a></li><li><ahref="#how-to-work-with-enums">How To Work With Enums</a></li><li><ahref="#determining-classes-of-java-objects">Determining Classes of Java Objects</a></li><li><ahref="#how-to-get-a-java-class-reference-by-name">How To Get a Java Class Reference By Name</a></li><ol><li><ahref="#array-types-primitives">Array Types, Primitives</a></li></ol><li><ahref="#implementing-java-interfaces-with-reify">Implementing Java Interfaces With reify</a></li><ol><li><ahref="#reify-parameter-destructuring-and-varargs">reify, Parameter Destructuring and Varargs</a></li><li><ahref="#example-1">Example 1</a></li></ol><li><ahref="#extending-java-classes-with-proxy">Extending Java Classes With proxy</a></li><li><ahref="#consuming-java-streams">Consuming Java Streams</a></li><li><ahref="#clojure-functions-implement-runnable-and-callable">Clojure Functions Implement Runnable and Callable</a></li><li><ahref="#gen-class-and-how-to-implement-java-classes-in-clojure">gen-class and How to Implement Java Classes in Clojure</a></li><ol><li><ahref="#overview-1">Overview</a></li><li><ahref="#aot">AOT</a></li><li><ahref="#class-definition-with-clojurecoregen-class">Class Definition With clojure.core/gen-class</a></li><li><ahref="#gen-class-in-the-ns-macro">gen-class In The ns Macro</a></li><li><ahref="#examples">Examples</a></li><li><ahref="#inspecting-class-signatures">Inspecting Class Signatures</a></li></ol><li><ahref="#how-to-extend-protocols-to-java-classes">How To Extend Protocols to Java Classes</a></li><li><ahref="#using-intrinsic-locks-synchronized-in-clojure">Using Intrinsic Locks ("synchronized") in Clojure</a></li><li><ahref="#wrapping-up">Wrapping Up</a></li><li><ahref="#contributors">Contributors</a></li></ol>
64
+
<olclass="toc"><li><ahref="#what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</a></li><li><ahref="#overview">Overview</a></li><li><ahref="#imports">Imports</a></li><ol><li><ahref="#automatic-imports-for-javalang">Automatic Imports For java.lang.*</a></li><li><ahref="#inner-nested-classes">Inner (Nested) Classes</a></li></ol><li><ahref="#how-to-instantiate-java-classes">How to Instantiate Java Classes</a></li><li><ahref="#how-to-invoke-java-methods">How to Invoke Java Methods</a></li><ol><li><ahref="#instance-methods">Instance Methods</a></li><li><ahref="#static-methods">Static Methods</a></li><li><ahref="#chained-calls-with-the-double-dot-form">Chained Calls With The Double Dot Form</a></li><li><ahref="#multiple-calls-on-the-same-object">Multiple Calls On the Same Object</a></li></ol><li><ahref="#how-to-access-java-fields">How to Access Java Fields</a></li><li><ahref="#how-to-set-java-fields">How to Set Java Fields</a></li><li><ahref="#how-to-work-with-enums">How To Work With Enums</a></li><li><ahref="#determining-classes-of-java-objects">Determining Classes of Java Objects</a></li><li><ahref="#how-to-get-a-java-class-reference-by-name">How To Get a Java Class Reference By Name</a></li><ol><li><ahref="#array-types-primitives">Array Types, Primitives</a></li></ol><li><ahref="#implementing-java-interfaces-with-reify">Implementing Java Interfaces With reify</a></li><ol><li><ahref="#functional-interface">Functional Interface</a></li><li><ahref="#reify-parameter-destructuring-and-varargs">reify, Parameter Destructuring and Varargs</a></li><ol><li><ahref="#example-reify">Example: reify</a></li><li><ahref="#example-functional-interface">Example: Functional Interface</a></li><li><ahref="#example-supplier">Example: Supplier</a></li></ol></ol><li><ahref="#extending-java-classes-with-proxy">Extending Java Classes With proxy</a></li><li><ahref="#consuming-java-streams">Consuming Java Streams</a></li><li><ahref="#clojure-functions-implement-runnable-and-callable">Clojure Functions Implement Runnable and Callable</a></li><li><ahref="#gen-class-and-how-to-implement-java-classes-in-clojure">gen-class and How to Implement Java Classes in Clojure</a></li><ol><li><ahref="#overview-1">Overview</a></li><li><ahref="#aot">AOT</a></li><li><ahref="#class-definition-with-clojurecoregen-class">Class Definition With clojure.core/gen-class</a></li><li><ahref="#gen-class-in-the-ns-macro">gen-class In The ns Macro</a></li><li><ahref="#examples">Examples</a></li><li><ahref="#inspecting-class-signatures">Inspecting Class Signatures</a></li></ol><li><ahref="#how-to-extend-protocols-to-java-classes">How To Extend Protocols to Java Classes</a></li><li><ahref="#using-intrinsic-locks-synchronized-in-clojure">Using Intrinsic Locks ("synchronized") in Clojure</a></li><li><ahref="#wrapping-up">Wrapping Up</a></li><li><ahref="#contributors">Contributors</a></li></ol>
65
65
<p>This guide covers:</p><ul><li>How to instantiate Java classes</li><li>How to invoke Java methods</li><li>How to extend Java classes with proxy</li><li>How to implement Java interfaces with reify</li><li>How to generate Java classes with gen-class</li><li>Other topics related to interop</li></ul><p>This guide does not cover how to include Java files in Clojure projects.
66
66
For that, head to <ahref="/articles/cookbooks/cli_build_projects/#including-java-code-in-a-clojure-project">including Java code in a Clojure project</a></p><p>This work is licensed under a <arel="license" href="https://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>
67
67
(including images & stylesheets). The source is available <ahref="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p><h2id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.12.</p><h2id="overview">Overview</h2><p>Clojure was designed to be a hosted language that directly interoperates with its host platform (JVM, JS, CLR and so on).
</code></pre><p>In Clojure 1.12, a Java interface that is declared <code>@FunctionalInterface</code> can
254
+
</code></pre><h3id="functional-interface">Functional Interface</h3><p>In Clojure 1.12, a Java interface that is declared <code>@FunctionalInterface</code> can
255
255
be inferred from from the context and can be satisfied with a regular Clojure
256
256
function. <code>java.io.FilenameFilter</code> is such an interface, so you can pass a
257
257
Clojure function directly to a Java method that expects a <code>FilenameFilter</code>:</p><pre><codeclass="clojure">(seq (.list (java.io.File. ".") #(str/starts-with? %2 ".")))
</code></pre><p>This will compile without error but when called, the first argument to
269
269
<code>accept</code> -- the directory object -- will be bound to <code>&</code> and the second
270
-
argument to <code>accept</code> -- the filename string -- will be bound to <code>more</code>.</p><h3id="example-1">Example 1</h3><p>The following example demonstrates how instances created with <code>reify</code> are passed around
270
+
argument to <code>accept</code> -- the filename string -- will be bound to <code>more</code>.</p><h4id="example-reify">Example: reify</h4><p>The following example demonstrates how instances created with <code>reify</code> are passed around
271
271
as regular Java objects:</p><pre><codeclass="clojure">(require '[clojure.string :as str])
</code></pre><p>As above, in Clojure 1.12, because <code>java.io.FilenameFilter</code> is a functional interface, you can pass a Clojure function directly:</p><pre><codeclass="clojure">(import java.io.File)
293
+
</code></pre><h4id="example-functional-interface">Example: Functional Interface</h4><p>As above, in Clojure 1.12, because <code>java.io.FilenameFilter</code> is a functional interface, you can pass a Clojure function directly:</p><pre><codeclass="clojure">(import java.io.File)
294
294
295
295
;; a file filter implementation that keeps only .edn files
296
296
(let [^java.io.FilenameFilter
297
297
f (fn [_dir name]
298
298
(str/ends-with? name ".edn"))
299
299
dir (File. "/home/sean/oss/clojure-doc.github.io/")]
300
300
(into [] (.listFiles dir f)))
301
-
</code></pre><blockquote><p>Note: we need the type hint on <code>f</code> here because <code>.listFiles</code> has multiple overloads for the same arity, and we need to distinguish a <code>FilenameFilter</code> from a <code>FileFilter</code>.</p></blockquote><h2id="extending-java-classes-with-proxy">Extending Java Classes With proxy</h2><p><code>proxy</code> is one of two ways to generate instances of anonymous classes in Clojure.
301
+
</code></pre><blockquote><p>Note: we need the type hint on <code>f</code> here because <code>.listFiles</code> has multiple overloads for the same arity, and we need to distinguish a <code>FilenameFilter</code> from a <code>FileFilter</code>.</p></blockquote><h4id="example-supplier">Example: Supplier</h4><p>Another change in Clojure 1.12 was to implement the
Jun 07, 2025 9:01:47 PM clojure.lang.Reflector invokeMatchingMethod
312
+
INFO: Compute Me!
313
+
</code></pre><p>The <code>Supplier</code> object is only dereferenced if the log message is actually
314
+
produced (i.e., the log level is high enough to log the message), so this can
315
+
be useful for deferring expensive computations until they are actually needed.</p><h2id="extending-java-classes-with-proxy">Extending Java Classes With proxy</h2><p><code>proxy</code> is one of two ways to generate instances of anonymous classes in Clojure.
302
316
<code>proxy</code> takes two vectors: one listing its superclass and (optional) interfaces, the other listing constructor signatures, as well as
303
317
zero or more
304
318
method implementations. Method implementations are identical to <code>reify</code> except that the <code>this</code> argument is
0 commit comments