GWT JSNI调用Java方法报错:JavaScriptException TypeError:方法不是函数
GWT调用Java实例方法报错:that_0_g$.doThing_0_g$ is not a function
问题概况
尝试通过JavaScript的onclick事件调用GWT中StartView类的doThing()实例方法,编译通过但触发点击时控制台抛出错误:
Exception: com.google.gwt.core.client.JavaScriptException: (TypeError) : that_0_g$.doThing_0_g$ is not a function
控制台输入window.doThing可正常返回函数,但调用时触发上述异常。相关代码如下:
关联代码
StartView.java(初始化时调用StartView.loadJS()):
public void doThing() { System.out.println("do thing"); } public static native void loadJS() /*-{ var that = this; $wnd.doThing = $entry(function() { that.@package.StartView::doThing()(); }); }-*/;
外部start.js(通过ScriptInjector注入):
// onclick 处理逻辑内 window.doThing();
错误根源
loadJS()是static静态方法,此时this指向的是StartView类本身(而非类的实例对象),但doThing()是实例方法——类本身并不拥有该方法,只有类的实例才具备,因此编译后尝试调用类上的doThing_0_g$方法必然失败。
解决方法
方案1:修正JSNI的this指向(适配现有代码)
将loadJS()改为实例方法,确保this指向StartView的实例:
// 改为实例方法,移除static修饰符 public native void loadJS() /*-{ var that = this; $wnd.doThing = $entry(function() { that.@package.StartView::doThing()(); }); }-*/; // 初始化时用实例调用该方法 StartView viewInstance = new StartView(); viewInstance.loadJS();
方案2:使用JSInterop替代JSNI(更简洁可靠)
利用GWT的JSInterop注解直接将实例方法绑定到全局window,避免this指向混淆:
import jsinterop.annotations.JsMethod; import jsinterop.annotations.JsPackage; import jsinterop.annotations.JsType; @JsType(isNative = false, namespace = JsPackage.GLOBAL) public class StartView { public void doThing() { System.out.println("do thing"); } @JsMethod(name = "doThing") public static void bindToWindow(StartView instance) { // 将实例方法绑定到全局window对象 $wnd.doThing = () -> instance.doThing(); } } // 初始化时传入实例完成绑定 StartView view = new StartView(); StartView.bindToWindow(view);
额外注意点
- 确保
StartView实例在window.doThing()调用期间未被GWT垃圾回收,可将实例存储在全局变量或保留类级别的引用。 - 验证编译模式:开发模式与生产模式的JS绑定逻辑存在差异,建议在生产编译环境下测试效果。
内容的提问来源于stack exchange,提问作者scoots
相关产品推荐
相关产品推荐

