【问题标题】:Clojure: gen-class and import it in java; packages, paths, classpathsClojure:gen-class并在java中导入;包、路径、类路径
【发布时间】:2018-01-01 14:43:26
【问题描述】:

我想调用从 Java 编译成类的 Clojure 代码。

Clojure 类:

(ns clj.core)

(gen-class
 :name de.wt.TestClj
 :state state
 :init init
 :prefix "-"
 :main false
 :methods [[setValue [String] void]
           [getValue [] String]])

(defn -init []
  [[] (atom {:value ""})])

(defn -setValue [this val]
  (swap! (.state this) assoc :value val))

(defn -getValue [this]
  (@(.state this) :value))

使用lein uberjar编译并将输出-standalone.jar复制到子目录de/wt下的Java项目中。

.java 文件:

import de.wt.TestClj;

class CljTest {
    public static void main(String args[]) {
        TestClj test = new TestClj();
        System.out.println("Pre: " + test.getValue());
        test.setValue("foo");
        System.out.println("Post: " + test.getValue());
    }
}

现在当我尝试编译时

~/testbed/cljava/java % tree                                                                 [1 14:44:53]
.
├── CljTest.java
├── de
│   └── wt
│       └── TestClj.jar
└── TestClj.jar

2 directories, 3 files
~/testbed/cljava/java % javac -cp ./:./de/wt/TestClj.jar CljTest.java                        

CljTest.java:1: error: package de.wt does not exist
import de.wt.TestClj;
^
CljTest.java:5: error: cannot find symbol
TestClj test = new TestClj();
^
symbol:   class TestClj
location: class CljTest
CljTest.java:5: error: cannot find symbol
TestClj test = new TestClj();
^
symbol:   class TestClj
location: class CljTest
3 errors

在命名文件/包、创建目录和设置类路径时我需要遵循什么方案?

【问题讨论】:

    标签: clojure clojure-java-interop java-interop


    【解决方案1】:

    您应该能够在您的 jar 中看到 java 类,例如:

     $ jar tvf target/default-0.1.0-SNAPSHOT-standalone.jar | grep TestClj
     2090 Mon Jan 01 18:43:12 CET 2018 de/wt/TestClj.class
    

    如果没有,请确保您的 project.clj 中有 :aot(提前编译)指令:

    (defproject default "0.1.0-SNAPSHOT"
      :description "FIXME: write description"
      :url "http://example.com/FIXME"
      :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
      :aot [clj.core]
      :dependencies [[org.clojure/clojure "1.7.0"]])
    

    在您的 jar 中看到 .class 文件后,该 jar 在您的类路径中,您在 Java 代码中的导入应该可以正常工作。

    如文档 (https://clojure.org/reference/compilation) 中所述:

    Clojure 将您即时加载的所有代码编译为 JVM 字节码,但有时提前编译 (AOT) 是有利的。使用 AOT 编译的一些原因是:

    在没有源代码的情况下交付您的应用程序

    加快应用程序启动

    生成 Java 使用的命名类

    创建不需要运行时字节码生成和自定义类加载器的应用程序

    另见http://clojure-doc.org/articles/language/interop.html:

    AOT

    gen-class 需要提前 (AOT) 编译。这意味着在使用 gen-class 定义的类之前,Clojure 编译器需要从 gen-class 定义中生成 .class 文件。

    【讨论】:

    • 感谢您的回答。我已经添加了:aot,但显然由于某种原因它没有干净地重建。你使用jar 命令的技巧很不错!
    • 现在我可以使用javac -cp ./TestClj.jar CljTest.java 编译并使用java -cp .:./TestClj.jar CljTest 运行。非常简单!
    猜你喜欢
    • 2011-12-13
    • 1970-01-01
    • 2018-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多