Где найти LinkedHashSet в jsinterop? - PullRequest
0 голосов
/ 15 мая 2019

У меня есть следующая сущность в 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. Но как я могу создать новый HashSet в JavaScript для использования myEntityVar.setTexts(texts)? Я пробовал массив для параметра «тексты», но это не работает. Поэтому мне как-то нужно использовать HashSet в JavaScript. Однако я не могу понять, где его найти. Есть идеи?

1 Ответ

6 голосов
/ 15 мая 2019

Короткий ответ: вы не можете, но опять же, вы также не можете создать простой HashSet в JS!

Причина, по которой это работает вообще, заключается в том, что вы включили -generateJsInteropExports, и хотя для вашего типа MyEntity есть аннотация JsInterop, есть также одна для java.util.Set (и несколько других).базовые типы JRE).Это позволяет вашему коду возвращать эмулированные наборы Java без проблем - поддерживается любой метод, совместимый с запуском в JS.

Есть несколько недостатков:

  • Скомпилированный размер несколько увеличивается, поскольку даже если вы не используете метод, он должен быть скомпилирован в ваше приложение таким образом, на случай, если JS использует его
  • Некоторые методы не поддерживаются - JS на самом деле не имеет перегрузки методов,поэтому toArray() и toArray(T[]) выглядят одинаково в JS.GWT решает эту проблему, вообще не поддерживая второй метод.(java.util.List имеет ту же проблему с remove(T) и remove(int), но устраняет ее путем переименования remove(int) в removeAtIndex(int) при компиляции.)

Если вы никогда не вернете эти типы,Вы, вероятно, захотите полностью отключить эту функцию - флаги -excludeJsInteropExports и -includeJsInteropExports для компилятора позволяют вам контролировать то, что экспортируется.


Чтобы ответить на ваш вопрос более прямо, у вас есть несколькопараметры, которые я вижу:

  • Разрешить методу setTexts передавать что-то еще из JS, например JsArrayLike, чтобы вы могли позволить пользователям передавать простой массив строк JS,или даже набор JS.Вы можете пойти дальше и принять Object, а затем проверить его, чтобы увидеть, что было передано. Вы даже можете оставить переопределение Set, чтобы его можно было вызывать из вашей собственной Java, если это необходимо, но пометить его как @JsIgnore чтобы GWT не ломался при попытке экспортировать перегруженные методы.
  • Создайте метод фабрики где-нибудь, чтобы создать реализацию Set, которую вы хотели бы использовать своим пользователям JS.Поскольку поддерживаются add и remove, вызывающий код JS может создать набор перед его передачей. Примерно так:

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

    Теперь они могут вызывать my.Util.createSet(), добавлять элементы изатем передайте его в ваш метод setTexts.

...