本文译自Registering Java Callbacks with J2V8,并加入了自己的一些理解。
使用 J2V8 时是可以使用 JavaScript 来调用 Java 的方法的,下面就介绍一些如何注册 Java 的回调函数来供 JavaScript 调用。
回调函数
在 JavaScript 中,函数也即是对象,可以被操作也可以被传递。在使用 J2V8 时,任何的 JavaScript 方法都可以映射到 Java 的方法之上,当这些方法被调用时,J2V8 就会调用 Java 的方法来代替,并把参数传递给 Java 的方法。
注册 Java 方法
Java 的方法可以通过两种方法注册为回调函数,可以通过实现 JavaCallback
接口来实现(如果没有返回值时,也可以通过 JavaVoidCallback
来实现),或者是反射地把已经实现的 Java 方法注册为回调函数。
JavaCallback
先来看下面一段代码:
1 | V8 v8 = V8.createV8Runtime(); |
执行结果:
1 | arg1 = hello, world |
上面的例子中创建了 JavaVoidCallback
的一个匿名内部类,把该类的一个实例注册为一个全局的作用域中的方法,并命名为 print
方法,那么我们在 JavaScript 中就可以向调用其他 JavaScript 的方法一样来调用 print
方法了。
通过反射来注册
先来看下面一段代码:
1 | public static class Console { |
执行结果:
1 | [INFO] hello, world |
在上面的例子中,一个已经实现的类的方法被注册为回调函数。
参数
参数可以从 JavaScript 传递到 Java,如果是通过实现 JavaCallback
来注册回调函数,那么参数会以 V8Array
的形式来传递。V8Array
包含了一些 V8Object
对象或者是一些原始数据。这些 V8Array
并不需要我们去释放,因为它不是由开发者创建的。但是任何从这个 V8Array
中获取的作为参数的 V8Object
都需要手动的进行释放,因为它们是作为方法调用的结果返回给你的。
如果方法是通过反射的方式进行注册的,那么这个方法的所有的参数类型都是已知的。在这种情形下,传递给 Javascript 函数的参数必须与作为它的回调函数的 Java 方法的一致。
接收器
当 JavaScript 调用通过 Java 注册的回调函数时,这个被调用的 JavaScript 对象会作为第一个参数进行传递。
看下面一段 JavaScript 代码:
1 | var array1 = [{first:'Ian'}, {first:'Jordi'}, {first:'Holger'}]; |
这中情况下 print
方法会被调用,并且 “says Hi.” 会被作为参数传递到 Java。但是当前的 JavaScript 会作为一个接收器被传递过来。
1 | class PersonPrinter implements JavaVoidCallback { |
执行结果:
1 | Ian says Hi. |
把调用者也打印出来了。
V8Function 类
在 J2V8 3.0 版本中,引入了一种 V8Function
类。V8Function
类是 V8Object
的子类,只要一个函数通过是 getObject()
调用被返回的话,那么返回的就是一个 V8Function
对象。V8Function
类有一个 call()
方法,可以使用它来在 Java 中调用 JavaScript 方法。