Где найти LinkedHashSet в 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;
   }

}

Когда я вызываю myEntityVar.getTexts() в Javascript, возвращаемый объект является HashSet. Кажется, что jsinterop преобразует реализацию HashSet в Java для JavaScript. Но как я могу создать новый HashSet в JavaScript, чтобы использовать myEntityVar.setTexts(texts) ? Я пробовал массив для параметра «тексты», но это не работает. Поэтому мне как-то нужно использовать HashSet в JavaScript. Однако я не могу понять, где его найти. Любая идея?

Всего 1 ответ


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

Причина, по которой это работает вообще, заключается в том, что вы включили -generateJsInteropExports , и хотя есть аннотация JsInterop для вашего типа MyEntity , есть также одна на 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.


Есть идеи?

10000