栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何从JavaScript调用Java实例的方法?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何从JavaScript调用Java实例的方法?

当要在范围内将java方法(静态或非静态)用作全局函数时,我们使用以下逻辑:

FunctionObject javascriptFunction = new FunctionObject( javascriptFunctionName,  javaMethod,  parentScope);boundScope.put(javascriptFunctionName, boundScope, javascriptFunction);

在这里,

boundScope
应该始终是要提供该功能的范围。

但是,父作用域的值取决于我们是绑定实例方法还是静态方法。对于静态方法,可以是任何有意义的范围。甚至可以与相同

boundScope

但是在使用实例方法的情况下,

parentScope
应该是绑定了方法的实例。

以上只是背景信息。现在,我将说明问题所在,并给出一个自然的解决方案,即允许直接将实例方法作为全局函数调用,而不是显式创建对象的实例,然后使用该实例调用方法的解决方案。

调用函数时,Rhino将调用

FunctionObject.call()
传递给的引用的方法
this
。如果函数是全局函数,则在不引用
this
(即
xxx()
代替
this.xxx()
)的情况下调用该函数,
this
传递给该
FunctionObject.call()
方法的变量的值就是进行调用的范围(即,在这种情况下,
this
参数将与参数的值相同
scope
)。

如果被调用的java方法是一个实例方法,这将成为一个问题,因为根据

FunctionObject
类的构造函数的JavaDocs :

如果该方法不是静态的,则Java

this
值将对应于Javascript
this
值。尝试使用
this
不正确的Java类型的值来调用该函数将导致错误。

在上述情况下,情况确实如此。javascript

this
值与java
this
值不对应,并导致不兼容的对象错误。

解决方案是子类化

FunctionObject
,重写
call()
方法,强行“固定”
this
引用,然后让调用正常进行。

所以像:

FunctionObject javascriptFunction = new MyFunctionObject(javascriptFunctionName, javaMethod, parentScope);boundScope.put(javascriptFunctionName, boundScope, javascriptFunction);private static class MyFunctionObject extends FunctionObject {    private MyFunctionObject(String name, Member methodOrConstructor, scriptable parentScope) {      super(name, methodOrConstructor, parentScope);    }    @Override    public Object call(Context cx, scriptable scope, scriptable thisObj, Object[] args) {      return super.call(cx, scope, getParentScope(), args);    }  }

我认为最好在下面粘贴一个自包含/完整的示例来理解。在此示例中,我们将实例方法:myJavaInstanceMethod(Double
number)公开为javascript范围(’scriptExecutionScope’)中的全局函数。因此,在这种情况下,“
parentScope”参数的值必须是包含此方法的类的实例(即Myscriptable)。

package test;import org.mozilla.javascript.*;import java.lang.reflect.Member;import java.lang.reflect.Method;//-- This is the class whose instance method will be made available in a Javascript scope as a global function.//-- It extends from scriptableObject because instance methods of only scriptable objects can be directly exposed//-- in a js scope as a global function.public class Myscriptable extends scriptableObject {  public static void main(String args[]) throws Exception {    Context.enter();    try {      //-- Create a top-level scope in which we will execute a simple test script to test if things are working or not.      scriptable scriptExecutionScope = new importerTopLevel(Context.getCurrentContext());      //-- Create an instance of the class whose instance method is to be made available in javascript as a global function.      scriptable myscriptable = new Myscriptable();      //-- This is not strictly required but it is a good practice to set the parent of all scriptable objects      //-- except in case of a top-level scriptable.      myscriptable.setParentScope(scriptExecutionScope);      //-- Get a reference to the instance method this is to be made available in javascript as a global function.      Method scriptableInstanceMethod = Myscriptable.class.getMethod("myJavaInstanceMethod", new Class[]{Double.class});      //-- Choose a name to be used for invoking the above instance method from within javascript.      String javascriptFunctionName = "myJavascriptGlobalFunction";      //-- Create the FunctionObject that binds the above function name to the instance method.      FunctionObject scriptableInstanceMethodBoundJavascriptFunction = new MyFunctionObject(javascriptFunctionName,   scriptableInstanceMethod, myscriptable);      //-- Make it accessible within the scriptExecutionScope.      scriptExecutionScope.put(javascriptFunctionName, scriptExecutionScope,   scriptableInstanceMethodBoundJavascriptFunction);      //-- Define a simple test script to test if things are working or not.      String testscript = "function simpleJavascriptFunction() {" +   "  try {" +   "    result = myJavascriptGlobalFunction(12.34);" +   "    java.lang.System.out.println(result);" +   "  }" +   "  catch(e) {" +   "    throw e;" +   "  }" +   "}" +   "simpleJavascriptFunction();";      //-- Compile the test script.      script compiledscript = Context.getCurrentContext().compileString(testscript, "My Test script", 1, null);      //-- Execute the test script.      compiledscript.exec(Context.getCurrentContext(), scriptExecutionScope);    } catch (Exception e) {      throw e;    } finally {      Context.exit();    }  }  public Double myJavaInstanceMethod(Double number) {    return number * 2.0d;  }  @Override  public String getClassName() {    return getClass().getName();  }  private static class MyFunctionObject extends FunctionObject {    private MyFunctionObject(String name, Member methodOrConstructor, scriptable parentScope) {      super(name, methodOrConstructor, parentScope);    }    @Override    public Object call(Context cx, scriptable scope, scriptable thisObj, Object[] args) {      return super.call(cx, scope, getParentScope(), args);//      return super.call(cx, scope, thisObj, args);    }  }}

如果要查看修复的行为,请取消注释行78和注释行79:

return super.call(cx, scope, getParentScope(), args);//return super.call(cx, scope, thisObj, args);

如果要查看没有修复的行为,请在注释行78和注释行79中:

//return super.call(cx, scope, getParentScope(), args);return super.call(cx, scope, thisObj, args);

希望这可以帮助。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/428099.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号