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

編集this-コメントに基づいて、toJS関数の代替バージョンを提供し、との間の混乱を避けましょう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();
    }-*/;

sayGiantWord("FEE")JavaScript内から(から適切に取得されたvarで)呼び出すことはtoJS()正しく機能しますか?言い換えると、JSNIマーシャラーは文字列を対応するJava列挙型に適切に変換しますか?

intは列挙型に簡単に変換できるため、呼び出しsayGiantWord(1)は正しくマーシャルする傾向があります。

その他の注意事項:

  • GWT Eclipseプラグインは、クラスメンバーの列挙型にアクセスするための構文を私に与えたものです。少なくともこれまでのところ、GWTは私と協力しています。
  • 数値を渡したくありません。必要に応じて、Javaクラスの変換関数で次のように文字列を処理できることを知っています。私はむしろそうしません。
public void sayGiantWordJS(String word) {
    // convert the string to an enum
    // call sayGiantWord
}

アドバイスありがとうございます!

4

2 に答える 2

1

Java列挙型はJSNIで処理できませんが、列挙型文字列を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エクスポーターを確認してください。

于 2013-02-22T17:36:51.823 に答える
0

列挙型をまったく機能させることができませんでした。サポートされていないようです。

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 に答える