JSNI Marshal Enums可以作为字符串吗?

时间:2013-02-19 17:07:41

标签: java javascript gwt marshalling jsni

我正在尝试使用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函数,避免在thisthis.之间混淆

    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可以很容易地转换为枚举。

其他说明:

  • GWT Eclipse插件为我提供了访问类成员枚举的语法。至少到目前为止,GWT正在与我合作。
  • 我不想传递数字,如果有必要,我知道我可以在Java类中使用转换函数处理字符串,如下所示;我宁愿不这样做。
public void sayGiantWordJS(String word) {
    // convert the string to an enum
    // call sayGiantWord
}

感谢您的任何建议!

2 个答案:

答案 0 :(得分:1)

JSNI无法处理Java枚举,但您可以将枚举字符串传递给JSNI层,并将从JSNI方法返回的字符串转换回枚举。

您最好分别代表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());
    }
}

vocabularysaid只是可以分配给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引发异常时出现奇怪的行为,但在您调用它时不会这样做。在我的测试中,在我做出的下一个用户界面操作之前,我没有看到异常。