gpt4 book ai didi

java - Nashorn访问非静态Java方法

转载 作者:行者123 更新时间:2023-11-29 21:54:34 26 4
gpt4 key购买 nike

在 Java 7 (1.7) 中,我可以通过运行以下命令从 JavaScript 访问 Java 方法:

ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");
jse.eval("importClass(net.apocalypselabs.symat.Functions);");
jse.eval("SyMAT_Functions = new net.apocalypselabs.symat.Functions();");

String input = "notify(\"Foo\");"; // This is user input

jse.eval("with(SyMAT_Functions){ "+input+" }");

将从 Functions java 类运行 notify() 函数:

public class Functions {
private Object someObjectThatCannotBeStatic;
public void notify(Object message) {
JOptionPane.showMessageDialog(null, message.toString());
}
/* Lots more functions in here, several working with the same non-static variable */
}

如何使用 Nashorn 引擎访问 Java 1.8 中的 Functions 类?如果用户使用 Java 1.8,我的目标是为第一个代码片段运行不同的代码,同时仍然允许使用 1.7 的人使用该应用程序。

我试过了 http://www.doublecloud.org/2014/04/java-8-new-features-nashorn-javascript-engine/ , https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/api.html , 和 How to instantiate a Java class in JavaScript using Nashorn?没有运气。它们似乎都不允许我像 Java 1.7 那样做同样的事情,而是假设我只想访问静态函数和对象。

我遇到的最常见错误:

我从……开始

ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");
jse.eval("var SyMAT_Functions;with (new JavaImporter(Packages.net.apocalypselabs.symat)) {"
+ "SyMAT_Functions = new Functions();}");

……那么……

jse.eval("with(SyMAT_Functions){ "+input+" }");

...吐出...

TypeError: Cannot apply "with" to non script object in <eval> at line number 1

最佳答案

我能够重现。首先,Nashorn 并没有试图让一般情况下使用 Java 对象(非静态或其他)变得困难。我在其他项目中使用过它,并且没有遇到任何超出 migration guide 中所涵盖内容的从 Java 7 中的 Rhino 转换的重大问题。 .但是,这里的问题似乎与 with statement 的使用有关。根据 MDN,这是“不推荐”的,甚至在 ECMAScript 5.1 的 strict 模式下也是不允许的。

与此同时,我找到了a thread on the Nashorn-dev mailing list讨论一个类似的案例。响应的相关部分是:

Nashorn allows only script objects (i.e., objects created by a JS constructor or JS object literal expression) as scope expression for "with" statement. Arbitrary objects . . . can not be used as 'scope' expression for 'with'.

In jdk9, support has been added to support script objects mirror other script engines or other globals (which are instances of ScriptObjectMirror).

这不是最优雅的解决方案,但在不使用 JDK 9 的情况下,我能够通过 在 Javascript 中编写代理对象 来实现 with 的预期用途镜像 Java 类的 public API:

package com.example;

import javax.script.*;

public class StackOverflow27120811
{
public static void main(String... args) throws Exception {
ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");
jse.eval(
"var real = new Packages.com.example.StackOverflow27120811(); " +
"var proxy = { doSomething: function(str) { return real.doSomething(str); } }; "
);
jse.eval("with (proxy) { doSomething(\"hello, world\"); } ");
}

public void doSomething(String foo) {
System.out.println(foo);
}
}

Attila Szegedi指出非标准 Nashorn Object.bindProperties功能。虽然它只能与 Nashorn 引擎一起使用,但它确实消除了在 proxy 对象中重新声明所有公共(public) API 的复杂性。使用这种方法,第一个 jse.eval(...) 调用可以替换为:

jse.eval(
"var real = new Packages.com.example.StackOverflow27120811(); " +
"var proxy = { }; " +
"Object.bindProperties(proxy, real); " // Nashorn-only feature
);

关于java - Nashorn访问非静态Java方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27120811/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com