在jsinterop中的哪里可以找到LinkedHashSet?

时间:2019-05-15 09:20:46

标签: gwt linkedhashset gwt-jsinterop

我在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;
   }

}

当我使用Javascript调用myEntityVar.getTexts()时,返回的对象是HashSet。似乎jsinterop将HashSet的java实现转换为JavaScript。但是,如何使用JavaScript创建新的HashSet以便使用myEntityVar.setTexts(texts)?我为“文本”参数尝试了一个数组,但这不起作用。因此,我需要以某种方式在JavaScript中使用HashSet。 但是,我不知道在哪里找到它。 有想法吗?

1 个答案:

答案 0 :(得分:6)

简短的回答是,您不能-但是再一次,您也不能在JS中创建普通的HashSet!

之所以完全有效,是因为您已启用-generateJsInteropExports,并且MyEntity类型上有一个JsInterop批注,而java.util.Set上也有一个(并且其他一些基本的JRE类型)。这样可以使您的代码无问题地返回仿真的Java集-支持与JS中运行兼容的任何方法。

有一些缺点:

  • 编译后的大小会有所增加,因为即使您不使用方法,也必须以这种方式将其编译到您的应用中,以防万一JS使用它。
  • 不支持某些方法-JS实际上没有方法重载,因此toArray()toArray(T[])看起来像JS中的相同方法。 GWT通过完全不支持第二种方法来解决此问题。 (java.util.Listremove(T)remove(int)有相同的问题,但是它在编译时通过将remove(int)重命名为removeAtIndex(int)来解决。)

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


要更直接地回答您的问题,我可以看到一些选择:

  • 允许setTexts方法从JS传递其他内容,例如JsArrayLike,以便您可以让用户传递纯字符串数组JS甚至是JS Set。您可以走得更远并接受Object,然后对其进行类型检查以查看传入的内容。您甚至可以保留Set覆盖,以便在必要时可以从您自己的Java中调用它,但请标记设置为@JsIgnore,这样当您尝试导出重载方法时GWT不会中断。
  • 在某处创建工厂方法以创建您希望JS用户使用的Set实现。由于支持addremove,因此调用JS代码可以在传入之前先构建集合。类似这样的东西:

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

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