我正在尝试使用GWT的JSNI通过本机代码调用Java函数。 Java函数有一个枚举,我很想知道枚举是否会以我想要的方式编组。我在Google或SO上找不到任何有用的内容,而the Google basic docs并不是非常具体。我确信在编译和运行时我会发现,但我想我也可以问。
鉴于这样的代码非常简单:
package my.example.package;
public class Giant {
public enum GiantWord { FEE, FIE, FO, FUM };
public void sayGiantWord(GiantWord word) { /* ... */ }
public native JavaScriptObject toJS() /*-{
var Giant = function() {
this.sayGiantWord = function(word) {
this.@my.example.package::sayGiantWord(Lmy/example/package/Giant$GiantWord;)(word);
};
};
return new Giant();
}-*/;
}
编辑 - 根据评论,让我提供一个替代版本的toJS函数,避免在this
和this.
之间混淆
public static native JavaScriptObject toJS(final Giant g) /*-{
var Giant = function() {
this.sayGiantWord = function(word) {
g.@my.example.package::sayGiantWord(Lmy/example/package/Giant$GiantWord;)(word);
};
};
return new Giant();
}-*/;
将从JavaScript中调用sayGiantWord("FEE")
(在toJS()
上适当获取的var)正常工作?换句话说,JSNI marshaller会将String正确转换为其匹配的Java枚举吗?
我希望调用sayGiantWord(1)
更容易正确编组,因为int可以很容易地转换为枚举。
其他说明:
public void sayGiantWordJS(String word) {
// convert the string to an enum
// call sayGiantWord
}
感谢您的任何建议!
答案 0 :(得分:1)
您最好分别代表Giant
JavaScript对象,并从Giant
Java类型委托给JSNI层。这样你就可以保持关注点的分离,并松散地结合实现和抽象:
public class GiantJso extends JavaScriptObject {
protected GiantJso() {
}
public static final native GiantJso create(String wordA, String wordB,
String wordC) /*-{
return {
vocabulary : [ wordA, wordB, wordC ],
said : ''
};
}-*/;
public final native void sayGiantWord(String word) /*-{
if (this.vocabulary.indexOf(word) != -1) {
console.log("i'm a giant, here me roar: ", word, "!");
this.said = word;
}
}-*/;
public final native JsArrayString vocabulary() /*-{
return this.vocabulary || null;
}-*/;
public final native String said() /*-{
return this.said;
}-*/;
}
然后将其包装在Java类型中:
public class Giant {
private GiantJso jso;
public Giant() {
jso = GiantJso.create(GiantWord.FEE.name(),
GiantWord.FEE.name(), GiantWord.FEE.name());
}
public void sayGiantWord(GiantWord word) {
jso.sayGiantWord(word.name());
}
public GiantWord getSaidWord() {
return GiantWord.valueOf(jso.said());
}
}
vocabulary
和said
只是可以分配给JSO的其他属性的示例,当然,您可以自由地实现任何您希望的结构。
注意:如果您要将Java类表示为JavaScript构造,请查看GWT exporter。
答案 1 :(得分:0)
我根本无法让Enum工作。它似乎得不到支持。
当我通过JavaScript对象传递字符串或数字时,JSNI没有尝试将输入转换为枚举。它确实将Enums转换为具有“序数”值的特殊对象,但它并未将该数字视为序数,并且未尝试查找valueOf
输入字符串。我考虑过在enum中添加一个构造函数,但是我所看到的一切都是为了在枚举中添加额外的数据字段。
我的回答是我说的我宁愿避免。最后,我的代码看起来与此类似:
package my.example.package;
public class Giant {
public enum GiantWord { FEE, FIE, FO, FUM };
public void sayGiantWord(GiantWord word) { /* ... */ }
public void sayGiantWordJS(String word) {
sayGiantWord(GiantWord.valueOf(word));
}
public static native JavaScriptObject toJS(final Giant g) /*-{
var Giant = function() {
this.sayGiantWord = function(word) {
g.@my.example.package::sayGiantWordJS(Ljava/lang/String;)(word);
};
};
return new Giant();
}-*/;
}
注意 - 如果您通过sayGiantWordJS()
传递了无效值,则会在valueOf
引发异常时出现奇怪的行为,但在您调用它时不会这样做。在我的测试中,在我做出的下一个用户界面操作之前,我没有看到异常。