java 板


LINE

Blog 版:http://blog.dontcareabout.us/2014/04/js-java-static-method.html BBS 版以 markdown 語法撰寫 ______________________________________________________________________ 內容有點無腦,先把結論寫在前面: > 外部 JS(官方文件稱為「handwritten JS」, > 其實不同 GWT Module 就滿足這個條件)要呼叫 Java 的 static method, > 必須先透過 JSNI 設定 `$wnd.methodName = > @fooPackage.FooClass::javaMethodName(*)`, > 後續使用 `$wnd.methodName()` 來達到目的。 > > 關鍵在於 JSNI 中: > > * `javaMethodName()` 後頭不需再加 `()`。 > * `javaMethodName()` 的參數某些情況下可以省略 field descriptor, > 直接用 `*` 代替。 update:感謝 darkk6(ptt.cc)提醒,讓我發現我不但死腦筋, 而且還少測了一種寫法... 所以文章就要重新翻修了 (艸 前天被問到一個問題: 「同一個 host page 上兩個不同 GWT Module 要怎麼溝通?」 我原本以為這不會是問題, 結果回到家實際測了一下才發現根本不是這麼一回事 [死]。 一言以蔽之,可以用這個 [stackoverflow][so1] 來解釋。 上頭發問的內容大抵上就是我原本的想法:用 event bus 來解, 結果是不可行的,不過那不是這篇文章的重點 XD [so1]: http://stackoverflow.com/questions/17273572/ how-to-communicate-two-modules-in-gwt?answertab=votes#tab-top 為了保險起見實際測試了一下解答的 code,然後就發現根本行不通: private native static exportMyJavaMethod() /*-{ $wnd.myJavaMethod = @my.package.module1.MyClass1::myJavaMethod; }-*/; 那個 `myJavaMethod` 沒給參數的 field descriptor, GPE 就報 syntax error、development mode 也一樣炸。 回頭去確認[官方文件],沒想到[官方文件]的程式碼一樣微妙...... package mypackage; public MyUtilityClass{ public static int computeLoanInterest( int amt, float interestRate, int term) { ... } public static native void exportStaticMethod() /*-{ $wnd.computeLoanInterest = $entry( @mypackage.MyUtilityClass::computeLoanInterest(IFI) ); }-*/; } 我不太確定那個 `IFI` 是啥意思 or 啥縮寫...... ==" [官方文件]: http://www.gwtproject.org/doc/latest/ DevGuideCodingBasicsJSNI.html#calling 好,不管這些,自己重新寫一個程式測試這個部份: package foo.client; //import 略 public class FooEP implements EntryPoint { @Override public void onModuleLoad() { exportJsMethod(); callFooMethod("..."); } static void javaMethod(String arg1) { Window.alert("javaMethod : " + arg1); } native static void exportJsMethod() /*-{ $wnd.fooMethod = @foo.client.FooEP::javaMethod (Ljava/lang/String;)(); }-*/; native static void callFooMethod(String message) /*-{ $wnd.fooMethod(message); }-*/; } 結果在 development mode 執行就炸錯誤,主要錯誤訊息是 com.google.gwt.core.client.JavaScriptException: (TypeError) @foo.client.FooEP::callFooMethod()([]): undefined is not a function 其實在這錯誤訊息之前就有兩個地方散發出怪味道: 1. `$wnd.fooMethod = @foo.client.FooEP::javaMethod (Ljava/lang/String;)();`, 為什麼沒有實際給 `javaMethod()` 參數? 等等,這個時間點給他什麼都不對啊? 2. 忽略 1,為什麼會先跳出 alert 視窗顯示 `javaMethod : null`, 然後才炸錯誤? 如果也在 `callFooMethod()` 裡頭先卡一行 `$wnd.alert("WTF?")`, 會發現顯示 `WTF?` 的 alert 視窗還是會出現, 表示 `callFooMethod()` 有正確被執行到,炸的是 `$wnd.fooMethod()`。 整個看起來,事情好像就有頭緒了。 其實 `exportJsMethod()` 的 `$wnd.fooMethod` 根本沒有正確 assign 成 `FooEP.javaMethod()`, 而是 assign 成 `FooEP.javaMethod()` 的回傳值──根本沒這玩意, 所以到 `callFooMethod()` 的時候當然就炸了。 原先我一直死腦筋用 Java 的角度去看, 後來換成 JS 的角度去看其實這樣結果很正常。 在 JS 當中一個變數可以代表一個數值、 也可以代表一個 function / method, 如果程式中要執行該 function / method,那就是加上 `()`, 例如在 Chrome console 輸入 `alert` 會得到 `function alert() { [native code] }`, 而 `alert("WTF")` 才會真正跳出 alert 視窗。 在上頭的 case 當中,我只是要把 $wnd.fooMethod 指定為一段程式碼, 根本沒有要執行它的意思,所以加上 `()` 根本就是多餘且錯誤阿... ![](http://img.anyanother.com/data/55495.jpg) 所以拿掉後頭的空括號,一切就正常了(之前怎麼沒想過阿阿阿阿 [核爆]), [官方文件]的那個 `IFI`, darkk6 猜測是 `int`、`float`、`int` 的縮寫, 如今(修正完之後)回頭看也很合理了 [死]。 最後不小心看到另一個 [stackoverflow][so2], 發現還有一招裏技可以用, 就是直接給 `*` 號,省去打一堆 field descriptor: native static void exportJsMethod() /*-{ $wnd.fooMethod = @foo.client.FooEP::javaMethod(*); }-*/; 這有個前提,就是 `FooEP` 中只能有一個 `javaMethod()`, 否則就會炸錯誤:也就是說, 如果你有兩個以上同名的 method,那還是得乖乖寫 field descriptor。 另外,在 JSNI 中呼叫 `$wnd.fooMethod()` 時已經是純粹 JS 了, 所以即使你多傳參數、或是少傳參數也不會怎麼樣...... 至少 GPE 跟 browser 都沒有特別反應。 native static void callFooMethod(String message) /*-{ $wnd.fooMethod(); $wnd.fooMethod(message, "又多餘了"); }-*/; [so2]: http://stackoverflow.com/questions/16080099/calling-gwt-java-function-from-javascript?rq=1 好了,事實證明 GWT 文件也沒寫得那麼好, 除了上次那個很隱晦不想讓人知道的 [AutoBean] 之外, 又遇到了一個謎樣裏技。還是說其實官方文件有,只是我沒找到呢...... [淚目] [AutoBean]: http://blog.dontcareabout.us/2013/12/gwt-autobean.html ==== 再次感謝 darkk6 Orz -- 錢鍾書: 說出來的話 http://www.psmonkey.org 比不上不說出來的話 Java 版 cookcomic 版 只影射著說不出來的話 and more...... --



※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.37.105.127
※ 文章網址: http://webptt.com/m.aspx?n=bbs/java/M.1398318539.A.066.html
1F:→ darkk6:不客氣XDD 是覺得應該和 JNI 的 Signatures 一樣才這樣猜 04/24 14:07







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:Gossiping站內搜尋

TOP