杰瑞科技汇

如何在JS中写Java代码?语法怎么转换?

这是一个非常有趣且常见的问题!直接在 JavaScript 中“写” Java 代码是不可能的,因为它们是两种完全不同的语言,运行在不同的环境上(Java 运行在 JVM 上,JavaScript 运行在浏览器、Node.js 等环境中)。

如何在JS中写Java代码?语法怎么转换?-图1
(图片来源网络,侵删)

根据你的真实需求,有几种非常常见的“桥接”方法可以实现这个目标,我会为你详细解释每一种方法。

核心思想:不能直接写,但可以“调用”

我们不能在 JS 文件里写 public class ...,但我们可以让 JavaScript 代码去执行调用一个已经写好的 Java 程序,并获取其结果。


通过命令行执行 Java 程序(最通用)

这是最基础也是最灵活的方法,你的 JavaScript 代码扮演一个“指挥官”的角色,它通过操作系统的命令行(Shell)来运行 Java 的编译和执行命令。

场景:你有一个独立的 Java 文件

假设你有一个 HelloWorld.java 文件:

// HelloWorld.java
public class HelloWorld {
    public static String sayHello(String name) {
        return "Hello from Java, " + name + "!";
    }
    public static void main(String[] args) {
        System.out.println(sayHello("World"));
    }
}

在 JavaScript (Node.js) 中调用它

Node.js 提供了 child_process 模块来执行外部命令。

编译并运行(一次性)

const { exec } = require('child_process');
// 1. 编译 Java 文件
exec('javac HelloWorld.java', (compileError, compileStdout, compileStderr) => {
    if (compileError) {
        console.error('编译失败:', compileStderr);
        return;
    }
    console.log('编译成功!');
    // 2. 运行 Java 类
    exec('java HelloWorld', (runError, runStdout, runStderr) => {
        if (runError) {
            console.error('运行失败:', runStderr);
            return;
        }
        console.log('Java 程序输出:', runStdout);
    });
});

更好的方式:将 Java 方法封装成一个可调用的命令

上面的例子只能运行 main 方法,如果我们想调用 sayHello 方法,并且想传递参数,更好的做法是让 Java 程序从标准输入读取参数,并从标准输出返回结果。

修改 HelloWorld.java

// HelloWorld.java
public class HelloWorld {
    public static void main(String[] args) {
        // 从命令行参数获取输入
        if (args.length > 0) {
            String name = args[0];
            String result = sayHello(name);
            // 将结果输出到标准输出,JS 可以捕获
            System.out.println(result);
        }
    }
    public static String sayHello(String name) {
        return "Hello from Java, " + name + "!";
    }
}

然后在 Node.js 中这样调用:

const { exec } = require('child_process');
// 使用引号确保参数能被正确传递
const javaProcess = exec('java HelloWorld "Node.js User"');
javaProcess.stdout.on('data', (data) => {
    // 捕获 Java 程序的标准输出
    console.log('从 Java 收到的消息:', data.toString());
});
javaProcess.stderr.on('data', (data) => {
    // 捕获错误信息
    console.error('Java 错误:', data.toString());
});
javaProcess.on('close', (code) => {
    console.log(`Java 进程退出,码: ${code}`);
});

优点:

  • 通用性强:任何可以编译成 .class 文件的 Java 代码都可以用这种方式调用。
  • 解耦:JS 和 Java 代码是分开的,可以独立开发和维护。

缺点:

  • 性能开销:每次调用都需要启动一个新的 JVM 进程,速度较慢。
  • 复杂:需要处理进程的启动、通信和错误。

使用 Java 生态的脚本引擎(如 Nashorn / GraalVM)

Java 从版本 8 开始内置了 Nashorn 引擎,可以直接在 JVM 中运行 JavaScript,反过来,我们也可以利用这个特性,通过一个“中间人”脚本让 JS 调用 Java,GraalVM 是一个更现代、性能更好的替代方案。

场景:你想要在 JVM 环境下实现 JS 和 Java 的深度互操作

使用 Nashorn (Java 8+)

Nashorn 允许你直接在 JavaScript 代码中导入和使用 Java 类。

// 在 Nashorn shell (jjs) 或 Nashorn 环境中运行
// 1. 直接使用 Java 标准库
var list = new java.util.ArrayList();
list.add("Hello");
list.add("from");
list.add("Nashorn!");
print(list);
// 2. 调用我们自己写的 Java 类
// 假设 HelloWorld.class 在 classpath 中
var hw = new HelloWorld();
var message = hw.sayHello("Nashorn User");
print(message);
// 3. 使用 Java 的静态方法
var system = java.lang.System;
print("当前 Java 版本: " + system.getProperty("java.version"));

使用 GraalVM (更现代)

GraalVM 提供了 js 命令,其 JavaScript 引擎不仅速度快,还支持与其他语言(如 Java、Python、Ruby)的无缝互操作。

# 安装 GraalVM 后,你可以这样运行
js -cp . HelloWorld.js

HelloWorld.js 文件中:

// 导入 Java 类
const HelloWorld = Java.type('HelloWorld');
// 创建 Java 类的实例
const hw = new HelloWorld();
// 调用 Java 方法
const message = hw.sayHello("GraalVM User");
// 在控制台打印
print(message);

优点:

  • 高性能:运行在同一个 JVM 中,没有进程创建的开销。
  • 无缝互操作:可以直接导入和使用 Java 类,像调用本地 JS 对象一样。
  • 强大的生态系统:可以轻松访问整个 Java 生态(如 Spring, Hibernate 等)。

缺点:

  • 环境限制:需要在安装了 GraalVM 或 Nashorn 的 Java 环境中运行。
  • 主要用于服务端:这种模式在浏览器中无法使用。

使用第三方库(如 JavaCPP)

JavaCPP 是一个强大的库,它允许你用 Java 代码调用 C/C++ 库,并提供了对许多高性能库(如 OpenCV, TensorFlow, FFmpeg)的预绑定,虽然它主要是为 C++ 设计的,但其原理也可以用于与任何本地代码交互。

优点:

  • 性能极高:通过 JNI (Java Native Interface) 与本地代码交互,性能开销极小。
  • 功能强大:可以调用几乎所有 C/C++ 库。

缺点:

  • 非常复杂:配置和使用门槛很高。
  • 间接性:你最终还是通过 Java 去调用,而不是直接从 JS 调用。

总结与选择建议

方法 核心原理 优点 缺点 适用场景
命令行执行 JS 通过 Shell 调用 javacjava 通用、解耦、简单易理解 性能差、有进程开销 简单的工具脚本、一次性任务、需要完全解耦的场景
脚本引擎 在 JVM 中运行 JS,JS 可直接调用 Java 高性能、无缝互操作、访问 Java 生态 需要特定 Java 环境(GraalVM/Nashorn) 服务端应用、需要深度集成 JS 和 Java 的项目
JavaCPP 通过 JNI 调用本地代码(C++/C) 性能极高 复杂、配置困难 需要调用特定高性能 C/C++ 库的场景

给你的建议:

  • 如果你只是想快速实现一个功能,不关心性能:选择 方法一(命令行执行),它最简单,也最容易上手。
  • 如果你正在构建一个高性能的服务端应用,希望 JS 和 Java 能紧密合作:选择 方法二(GraalVM),这是目前最先进、体验最好的方式。
  • 如果你的核心逻辑在一个现有的、复杂的 Java 库中,并且性能至关重要:可以考虑 方法二(GraalVM)方法三(JavaCPP),但前者通常更简单。

对于绝大多数现代开发者来说,GraalVM (方法二) 是实现“在 JavaScript 中写 Java 代码”这个目标的最优雅、最强大的解决方案。

分享:
扫描分享到社交APP
上一篇
下一篇