1

我正在尝试使用 GWT 的 JSNI 通过本机代码调用 Java 函数。Java 函数中有一个枚举,我很想知道枚举是否会以我想要的方式编组。我在 Google 或 SO 上找不到任何有用的东西,而且Google 基本文档也不是很具体。我相信我会在编译和运行时发现,但我想我不妨问问。

给定这样的大大简化的代码:

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();
    }-*/;

sayGiantWord("FEE")从 JavaScript 中调用(在适当获取的 var from 上toJS())是否可以正常工作?换句话说,JSNI 编组器会正确地将字符串转换为其匹配的 Java 枚举吗?

我希望调用sayGiantWord(1)更容易正确编组,因为 int 可以轻松转换为枚举。

其他注意事项:

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

感谢您的任何建议!

4

2 回答 2

1

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

您最好单独表示JavaScript 对象,并从Java 类型Giant委托给 JSNI 层。Giant这样,您可以保持关注点分离并松散地耦合实现和抽象:

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

于 2013-02-22T17:36:51.823 回答
0

我根本无法让 Enum 工作。好像不支持。

当我通过 JavaScript 对象传递字符串或数字时,JSNI 没有尝试将输入转换为枚举。它确实将枚举转换为具有“序数”值的特殊对象,但它没有将数字视为序数,也没有尝试查找valueOf输入字符串。我考虑向枚举添加一个构造函数,但我所看到的一切都表明这是为了向枚举添加额外的数据字段。

我的回答是我说我宁愿避免的那个。最后,我的代码看起来类似于:

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引发异常,但在调用它时不会这样做。在我的测试中,直到我执行下一个用户界面操作时才看到异常。

于 2013-02-21T15:24:25.483 回答