Java Nashorn中的(De)引用方法变体

(De)referencing method variant in Java Nashorn

本文关键字:引用 方法 De Nashorn 中的 Java      更新时间:2023-09-26

考虑代码:

例 1

var Executors = java.util.concurrent.Executors;
var executor = Executors.newCachedThreadPool();
var fork = function (callable) {
    // Clarify Runnable versus Callable overloaded methods
    executor['submit(java.util.concurrent.Callable)'](callable);
};
fork(function(){ ... }); //ok

这行得通。

但这不起作用:

例 2

var Executors = java.util.concurrent.Executors;
var executor = Executors.newCachedThreadPool();
var fork = executor['submit(java.util.concurrent.Callable)'];
fork(function(){ ... }); //fails, NullPointerException

我认为,这是因为这里的fork不是JS函数实例,它实际上是jdk.internal.dynalink.beans.SimpleDynamicMethod的实例

我试图使用fork.apply(executor,function() { ... });但本质上,简单动态方法没有apply

实际上,为什么示例 2 不起作用,而示例 1 有效?

这仅仅是纳索恩的福利吗?有没有比示例 1 更好的方法来定义 fork() 函数?

更新

在示例 2 中,

print(typeof fork);报告function

print(fork)报告[jdk.internal.dynalink.beans.SimpleDynamicMethod Future java.util.concurrent.AbstractExecutorService.submit(Callable)]

例外是(第 13 行读取 fork(function() {

Exception in thread "main" java.lang.NullPointerException
    at jdk.nashorn.internal.scripts.Script$'^eval'_._L5(<eval>:13)
    at jdk.nashorn.internal.scripts.Script$'^eval'_.runScript(<eval>:5)
    at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:527)

不幸的是,目前你不能在 POJO 方法中使用 bindapplycall。我想将其添加为将来的增强功能。在上面的例子中,你目前能做的最好的事情是:

executor['submit(Callable)'](function() { ... })

请注意,虽然在一般情况下,对属性的索引访问(使用 [] 运算符)的效率低于属性名称访问(使用 . 运算符),但 Nashorn 使用字符串文本识别索引访问,并将其视为与属性名称访问一样有效,因此您不会在这里遇到速度减慢,只是有点视觉噪音。在上面的情况下,它实际上最终会直接链接到执行者的虚拟方法。

说到视觉噪音,您不必完全限定java.util.concurrent.Callable。当参数类型的非限定名称足以消除重载的歧义时(几乎总是如此),您可以只使用非限定名称,无论它在哪个包中(也适用于您自己的类)。

问题是您在调用中缺少接收方"执行器"。 一般来说,"获取"Java函数只适用于静态Java函数。例如:

jjs> var abs = java.lang.Math.abs;
jjs> abs(-10);
10

在您的示例中,我们可以将 fork 绑定到执行器并使其等效为静态。 此支持当前不存在。 如果从类中"获取",我们可能应该支持将接收器添加为第一个参数。 将为将来的版本提交增强请求。

Alex,

在示例 1 中,var fork 是一个返回数组 executor 的函数。在示例 2 中,var fork是一个数组。这就是为什么你不能使用 ()apply .

fork[0](function(){...})对你有用吗?

谢谢