0

我在 GWT 中有以下实体

@JsType(namespace = "my.entities")
public class MyEntity {
   private Set<String> texts;
   public Set<String> getTexts(){
       if(this.texts==null)
           this.texts=new LinkedHashSet<String>();
       return this.texts;
   }

   public void setTexts(Set<String> texts){
       this.texts=texts;
   }

}

当我myEntityVar.getTexts()在 Javascript 中调用时,返回的对象是一个 HashSet。似乎 jsinterop 将 HashSet 的 java 实现转换为 JavaScript。但是我怎样才能在 JavaScript 中创建一个新的 HashSet 以便使用myEntityVar.setTexts(texts)呢?我为“文本”参数尝试了一个数组,但这不起作用。所以我不知何故需要在 JavaScript 中使用 HashSet。但是,我不知道在哪里可以找到它。任何想法?

4

1 回答 1

6

简短的回答是你不能——但话又说回来,你也不能在 JS 中创建一个普通的 HashSet !

这完全有效的原因是您已启用-generateJsInteropExports,并且虽然您的MyEntity类型上有一个 JsInterop 注释,但也有一个 on java.util.Set(以及一些其他基本 JRE 类型)。这允许您的代码毫无问题地返回模拟的 Java 集 - 支持任何与在 JS 中运行兼容的方法。

有几个缺点:

  • 编译后的大小有所增加,因为即使您不使用方法,也必须以这种方式将其编译到您的应用程序中,以防 JS 使用它
  • 不支持某些方法 - JS 并没有真正的方法重载,因此toArray()看起来toArray(T[])就像 JS 中的相同方法。GWT 通过根本不支持第二种方法来解决这个问题。(与andjava.util.List有相同的问题,但它通过在编译时重命名为来解决。)remove(T)remove(int)remove(int)removeAtIndex(int)

如果您从不返回这些类型,您可能希望完全禁用此功能 - 编译器的-excludeJsInteropExportsand-includeJsInteropExports标志让您可以控制导出的内容。


为了更直接地回答您的问题,我可以看到您有几个选项:

  • 允许该setTexts方法从 JS 传递其他东西,例如 aJsArrayLike这样您就可以让用户传入一个普通的 JS 字符串数组,甚至是一个 JS Set。您可以更进一步并 accept Object,然后对其进行类型检查以查看传入的内容。您甚至可以保留Set覆盖,以便在必要时可以从您自己的 Java 调用它,但将其标记为@JsIgnoreGWT 不会中断你试图导出重载的方法。
  • 在某处创建工厂方法来创建您希望 JS 用户使用的 Set 实现。由于addremove受支持,调用 JS 代码可以在传入之前构建集合。像这样:

    @JsMethod(namespace = "my.Util")
    public static <T> LinkedHashSet<T> createSet() {
      return new LinkedHashSet<>();
    }
    

    现在他们可以调用my.Util.createSet()、追加项目,然后将其传递给您的 setTexts 方法。

于 2019-05-15T12:52:09.447 回答