在使用 Nashorn 引擎时,传递 匿名类 或 非公共类 的对象到 bindings 中可能会遇到一些问题,这通常是由于 Java 对象的作用域、匿名类的封装方式以及 类的绑定机制 造成的。以下是一些常见原因和解决方案。
出现错误:
Exception in thread “main” javax.script.ScriptException: TypeError: outer.printMessage is not a function in at line number 1
at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:470)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:454)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:406)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:402)
at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:155)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
at com.ScriptEngineExample.main(ScriptEngineExample.java:27)
为什么 javax.script 使用匿名类和非公共类的对象不能暴露给脚本引擎?
在 Java 中,javax.script 提供了一个用于执行脚本语言的 API,常用于将 Java 与脚本语言(如 JavaScript、Groovy、Python 等)集成。这个 API 的核心组件是 ScriptEngine,它允许 Java 代码与脚本引擎交互,执行脚本并传递 Java 对象。然而,在将 Java 对象暴露给脚本引擎时,匿名类和非公共类的对象不能直接传递给脚本引擎,这背后有一些技术细节和设计上的原因。
- 脚本引擎和类加载器的隔离性
javax.script API 允许脚本引擎通过其特定的类加载器执行代码。脚本引擎需要能够访问和使用 Java 对象,但当我们使用匿名类或非公共类时,这些类的可见性受到了限制。
匿名类:匿名类是在 Java 中动态创建的,它没有显式的类名。其内部的类名通常是由编译器自动生成的,形式为 ClassName$1。这些类是局部的,通常只能在特定的方法或代码块中访问,因此它们的访问范围有限。
非公共类:如果一个类被声明为 private、protected 或者包级私有(即没有 public 修饰符),则该类只能在特定的包或类中访问,无法在外部代码中使用。这意味着脚本引擎无法访问这些类,因为它们的可见性受限于 Java 的访问控制机制。
1. 匿名类的绑定问题:
匿名类的行为:匿名类是在运行时动态生成的类,通常它们会继承某个具体类或实现接口,因此它们的行为可能与普通类有所不同。Nashorn 无法直接从 JavaScript 代码中访问匿名类的所有成员,因为匿名类的内部实现是自动生成的,且会隐式继承父类。
2. 匿名类绑定问题:
如果你要传递一个 匿名类的实例 到 Nashorn,你需要确保匿名类的实例正确地暴露到绑定中。
示例:
假设我们有一个 匿名类 和一个外部类,并想将其绑定到 Nashorn 引擎中:
package com;
import javax.script.*;
import com.MyClass;
public class ScriptEngineExample {
public static void main(String[