我会从几个层面来详细解释“JavaScript使用Java”这件事:

- 最直接的方式:在JavaScript代码中调用Java代码 (通过特定技术)
- 最常见的方式:在Java应用中嵌入和运行JavaScript (这是更主流的用法)
- 在Web开发中的协同工作 (前后端分离)
- 一些重要的历史和概念澄清
最直接的方式:在JavaScript中调用Java
这是你问题字面意义上的答案,要让JavaScript(通常是浏览器中的JS)能够调用Java代码,你需要一个“桥梁”或“胶水层”,因为浏览器本身不认识Java,它只认识JavaScript。
主要技术:Nashorn (已过时) 和 GraalVM
A. Nashorn (在Java 8中引入,Java 11中移除)
Nashorn是JDK(Java开发工具包)中的一个JavaScript引擎,它允许你在Java虚拟机上直接运行JavaScript代码,反过来,它也提供了在JavaScript中调用Java类和方法的能力。
工作原理: Nashorn将JavaScript代码编译成Java字节码,然后在JVM上执行,这使得JS可以无缝地访问Java的整个生态系统。
如何使用:

-
启动Nashorn Shell:
jjs
-
在JS中调用Java标准库:
// 导入Java类 var ArrayList = Java.type('java.util.ArrayList'); // 创建Java对象 var list = new ArrayList(); // 调用Java方法 list.add("Hello"); list.add("from"); list.add("JavaScript!"); // 遍历Java集合 for (var i = 0; i < list.size(); i++) { print(list.get(i)); }输出:
Hello from JavaScript! -
在JS中调用自定义Java类: 假设你有一个Java文件
MyJavaClass.java:
(图片来源网络,侵删)// MyJavaClass.java public class MyJavaClass { public String sayHello(String name) { return "Hello, " + name + " from Java!"; } }你可以在JS中这样调用:
jjs MyJavaScript.js
MyJavaScript.js文件内容:// 加载编译好的Java类文件 load("MyJavaClass.class"); // 获取Java类类型 var MyClass = Java.type('MyJavaClass'); // 创建实例并调用方法 var myInstance = new MyClass(); var result = myInstance.sayHello("Nashorn User"); print(result);输出:
Hello, Nashorn User from Java!
注意: Nashorn已经在Java 11中被移除了,不再被推荐使用。
B. GraalVM (现代替代方案)
GraalVM是一个现代的高性能JVM实现,它包含了新的JavaScript引擎(名为Graal.js),并且是Nashorn的继任者,它比Nashorn更强大,性能更好,并且支持多种语言互操作。
如何使用: GraalVM的使用方式与Nashorn类似,但功能更强大,它不仅能让你在JS中调用Java,还能调用其他运行在GraalVM上的语言(如Python, Ruby, R等)。
最常见的方式:在Java应用中嵌入和运行JavaScript
这其实是更普遍、更有用的场景,很多Java应用(如服务器端程序、桌面应用)需要具备脚本能力,比如执行用户提供的动态逻辑、配置文件等,这时,在Java中嵌入一个JavaScript引擎就非常理想。
主要技术:
- Nashorn (Java 8)
- GraalVM.js (Java 11+)
- 第三方库:如Rhino (Mozilla的JS引擎,常用于Android)
如何使用 (以GraalVM.js为例):
-
添加依赖: 如果你使用Maven,添加GraalVM的SDK依赖。
<dependency> <groupId>org.graalvm.js</groupId> <artifactId>js</artifactId> <version>23.1.0</version> <!-- 使用最新版本 --> </dependency> -
在Java中执行JS代码:
import org.graalvm.js.scripting.JS; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; public class JavaRunJS { public static void main(String[] args) { // 获取JS引擎 ScriptEngine engine = new ScriptEngineManager().getEngineByName("graal.js"); if (engine == null) { System.out.println("Graal.js engine not found!"); return; } try { // 执行简单的JS表达式 engine.eval("var message = 'Hello from JavaScript inside Java!';"); engine.eval("print(message);"); // 执行一个JS函数 engine.eval("function add(a, b) { return a + b; }"); // 从Java调用JS函数 Object result = engine.eval("add(10, 20);"); System.out.println("Result from JS function: " + result); // 输出 30 } catch (ScriptException e) { e.printStackTrace(); } } }
高级用法:在Java和JS之间传递对象
GraalVM/Nashorn允许你传递Java对象给JS,JS可以像调用普通JS对象一样调用该对象的方法。
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class JavaObjectToJS {
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("graal.js");
// 创建一个Java对象
MyJavaService service = new MyJavaService();
// 将Java对象注入到JS的全局变量中
engine.put("myService", service);
// 执行JS代码,可以操作Java对象
engine.eval("print('Calling Java method from JS...');");
engine.eval("var result = myService.greet('GraalVM User');");
engine.eval("print('Result: ' + result);");
}
}
class MyJavaService {
public String greet(String name) {
return "Java says: Welcome, " + name + "!";
}
}
输出:
Calling Java method from JS...
Result: Java says: Welcome, GraalVM User!
在Web开发中的协同工作 (前后端分离)
这是最广为人知的模式,虽然JavaScript和Java运行在不同的环境中,但它们通过API进行通信,共同构建一个完整的Web应用。
- 前端: 使用HTML, CSS, JavaScript (以及React, Vue, Angular等框架) 构建用户界面,运行在用户的浏览器中。
- 后端: 使用 Java (以及Spring Boot, Jakarta EE等框架) 构建服务器端应用,负责业务逻辑、数据库操作和API服务。
工作流程:
- 用户在浏览器中点击一个按钮。
- 前端的JavaScript代码向服务器发送一个HTTP请求(使用
fetch或axios)。 - 后端的Java应用(如一个Spring Boot的
@RestController)接收到这个请求。 - Java代码执行业务逻辑(比如查询数据库、处理数据)。
- Java应用将处理结果格式化为JSON或XML。
- Java应用将JSON数据作为HTTP响应返回给浏览器。
- 浏览器的JavaScript代码接收到这个JSON响应,然后动态地更新页面内容,展示给用户。
示例:
-
前端 (JavaScript):
async function fetchUserData() { try { const response = await fetch('https://my-java-api.com/users/123'); const user = await response.json(); // 将JSON响应解析为JS对象 console.log('User data:', user.name); } catch (error) { console.error('Error fetching user:', error); } } fetchUserData(); -
后端 (Java - Spring Boot):
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @GetMapping("/users/{id}") public User getUser(@PathVariable String id) { // 模拟从数据库获取数据 User user = new User(); user.setId(id); user.setName("John Doe"); user.setEmail("john.doe@example.com"); return user; // Spring Boot会自动将对象序列化为JSON } } class User { private String id; private String name; private String email; // Getters and Setters... }
历史和概念澄清
-
JavaScript vs. Java:
- JavaScript 是一种轻量级的、解释型的脚本语言,主要用于Web浏览器,但现在也用于服务器端(Node.js)和桌面应用。
- Java 是一种强类型的、编译型的面向对象编程语言,以其“一次编写,到处运行”(WORA)的跨平台能力而闻名,广泛用于企业级后端应用、安卓开发等。
- 它们是两种完全不同的语言,只是名字有点像。
-
JVM (Java虚拟机):
- 这是Java程序运行的环境,JVM负责将Java字节码转换为特定机器的指令来执行。
- 像Nashorn和GraalVM这样的技术,就是把JavaScript“翻译”成JVM能理解的字节码,从而让JS也能享受到JVM的平台无关性和优化。
| 场景 | 如何实现 | 核心技术 | 主要用途 |
|---|---|---|---|
| JS调用Java | 在JS环境中直接调用Java类和方法 | GraalVM, Nashorn (过时) | 在脚本环境中利用Java强大的库和生态。 |
| Java调用JS | 在Java应用中嵌入并执行JS脚本 | GraalVM.js, Nashorn, Rhino | 为Java应用增加动态脚本能力,如配置、插件等。 |
| 前后端协同 | 通过HTTP API通信 | JavaScript (前端) + Java (后端) | 构建现代化的全栈Web应用。 |
“JavaScript使用Java”这句话,根据上下文可以指代以上几种不同的技术实现,在现代开发中,在Java应用中嵌入GraalVM.js 和 前后端通过API协同 是最主流和最实用的两种方式。
