如何使用 Clojure 的 gen-class 创建多个 Java 成员变量

How to create multiple Java member variables with Clojure's gen-class

This answer 到一个关于 Clojure 的非常古老的问题-Java interop 解释了如何使用 gen-class:state:init 关键字来创建一个单个 public 实例变量可从 Java 访问。如果您只需要一份数据可用于 Java classes,或者如果您可以要求 Java classes 使用读取的访问函数,这就足够了,例如,存储在状态变量中的地图。此方法还允许更改数据,例如通过将 atoms 存储在状态变量中。

如果我想创建多个在 Java class 中可直接读取的实例变量怎么办?这可能吗?例如,我可以编译以下文件并执行 Bar class,并看到 foo.bar 的值 42 打印出来。

Foo.clj:

(ns students.Foo
  (:gen-class
    :name students.Foo
    :state bar
    ; :state baz
    :init init))

(defn -init
  []
  [[] 42])

Bar.java:

package students;

public class Bar {

    public static void main(String[] args) {
        Foo foo = new Foo();
        System.out.println(foo.bar);
        // System.out.println(foo.baz);
    }
}

如果我取消注释 baz 行,Bar.java 将不会编译——编译器似乎随机创建 barbaz 作为状态变量Foo,因此 Bar 只有其中一个可用。无论如何,我看不到如何使用 init 函数初始化 barbaz

gen-class 宏不支持定义多个 public 字段。您必须改用 defrecord 宏或 deftype 宏。

(defrecord Foo [bar baz])

遗憾的是,defrecord宏和deftype宏都没有准备方法来定义它们的构造函数。因此,在强制初始化多个实例变量的情况下,在 Java.

中编写 Java class 并没有什么可耻的