Как я могу переключить класс или улучшить это

#java

Вопрос:

 public <T> T getData(final Class<T> cast, final String query)
{
    final Optional<JSONObject> optional = Optional.ofNullable(new JSONObject(getHTTP(query))).filter(s -> s.has("data") amp;amp; s.getJSONArray("data").length() > 0 amp;amp; s.getJSONArray("data").get(0) instanceof JSONObject);

    if (optional.isPresent())
    {
        final JSONObject json = JSONObject.class.cast(optional.get().getJSONArray("data").get(0));

        return switch (cast.getSimpleName())
        {
            case Profile.class -> new Profile(<parameters>);
            case UserVideo.class -> new UserVideo(<parameters>);
            default -> null;
        };
    }

    return null;
}
 

Я хочу улучшить этот код и назвать его так

 final Profile profile = getData(Profile.class, String.format(URL, "data"))
 

Проблема в том, что я не могу переключить класс и не хочу использовать строку (так как я хочу расширить свои знания и сделать их более сложными, чем простыми).

Существует ли какой-либо другой способ переключить класс и проанализировать (или даже отразить класс), используя различные параметры, и вернуть его. Учтите, что этот метод может возвращать различные типы классов, и вы предоставляете только ССЫЛКУ и запрошенные данные.

Комментарии:

1. В Java switch-это оператор, а не оператор, поэтому вы не можете использовать его внутри выражения. Вы можете использовать оператор ?: внутри выражения, но это дает вам только два последовательных значения.

2. Ваш комментарий бесполезен, так как я уже это знаю. Я ищу другой подход.

3. Это switch кажется неудобным и не очень полезным. Я бы просто вернул метод Optional<JSONObject> (и никогда не возвращал null), и пусть каждый фрагмент вызывающего кода решает, что с ним делать.

4. @Christopher Начиная с JEP-361 (Java 14), переключатель также можно использовать в качестве выражения.

5. Отличная новая функция. Спасибо. Мне также нравится расширенная идея instanceof.

Ответ №1:

К сожалению, переключение на java не так мощно, как на других языках. Я думаю, что единственный способ сделать это-через цепочку if-elseif

 if (cast == Profile.class) { ... }
else if (cast == UserVideo.class) { ... }
else { return null; }
 

Но если вы позволите мне перепроектировать API, я предпочитаю:

 public JSONObject getData(String query) { ... }
---
profile = Profile.fromJSON(getData(String.format(URL, "data")))
---
class Profile {
  static Profile fromJSON(JSONObject json) {
    return new Profile(...)
  }
}
 

Редактировать:

Подожди, у меня появилась новая идея

 public <T> T getData(Function<JSONObject, T> cast, String query) {
   JSONObject json = ...;
   return cast.apply(json);
}

profile = getData(Profile::fromJSON, String.format(URL, "data"))
 

что эквивалентно моему предыдущему ответу, но выглядит немного более похоже на ваш код.


Изменить 2:

Если вам не нравится Profile::FromJSON, вы также можете использовать статическую константу.

 static final Function<JSONObject, Profile> PROFILE = json -> new Profile(...);

profile = getData(PROFILE, ...)
 

Комментарии:

1. В Java 17 появится функция предварительного просмотра JEP-406 Сопоставление шаблонов для switch (Предварительный просмотр) , которая позволит вам сделать что-то подобное с switch.

2. @MarkRotteveel Если я правильно понимаю, сопоставление шаблонов в java работает на основе типа объекта (или структуры), а не идентичности. So switch (someClass) { case Some.class -> ... } не поддерживается , потому что он сравнивает a == b , а не a instanceof B .