Можно ли использовать отражение, чтобы получить конкретный тип реализации (например, класс)? - PullRequest
0 голосов
/ 08 октября 2018

Моя цель - отразить все статические классы в классе контейнера и собрать их в карту simpleName -> class.

Это можно сделать «вручную» без проблем, но я бы очень хотел сделать это программно.

Например, задано:

public interface MyInterface {
    void doThing();
}

И класс, содержащий несколько классов, реализующих этот интерфейс

public class MyStuff {
    public static class One implements MyInterface {...}
    public static class Two implements MyInterface {...}
    public static class Three implements MyInterface {...}
}

Следующая карта, созданная вручную, работает A-OK.

public void demo(String jsonString) {
    Map<String, Class<? extends MyInterface>> myMap = ImmutableMap.of(
        "One", One.class,
        "Two", Two.class,
        "Three", Three.class,
    )

}

И я могу использовать его для таких полезных вещей, как десериализация с Gson:

MyInterface object = new Gson().fromJson(jsonString, myMap.get("One"))

Теперь я хотел бы сделать , а не buildэту карту вручную, но вместо этого используйте отражение, чтобы построить ее.

В идеале, что-то вроде:

Map<String, Class<? extends MyInterface>> options = new HashMap<>();
for (Class<?> cls : MyStuff.class.getDeclaredClasses()) {
    options.put(cls.getSimpleName(), cls)
}

Но это не компилируется, так как getDeclaredClasses фиксируется на Class<?>.

Интересно, что Java, похоже, обладает всей необходимой информацией во время выполнения.Я могу распечатать каждый класс и увидеть, что это правильный реализующий класс MyInterface.Я чувствую, что я должен быть в состоянии получить нужные мне типы.Однако я не могу понять, как сделать этот последний переход во время компиляции, чтобы получить Class<? extends MyInterface>

Возможно ли это в Java?

1 Ответ

0 голосов
/ 08 октября 2018

Если вам требуется, чтобы вложенный класс реализовывал MyInterface, вы должны проверить это, и, как только вы это сделаете, вы можете безопасно привести значение.

private static Map<String, Class<? extends MyInterface>> buildOptions() {
    Map<String, Class<? extends MyInterface>> options = new HashMap<>();
    for (Class<?> cls : MyStuff.class.getDeclaredClasses()) {
        if (MyInterface.class.isAssignableFrom(cls)) {
            options.put(cls.getSimpleName(), cls.asSubclass(MyInterface.class));
        }
    }
    return Collections.unmodifiableMap(options); // Make it immutable
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...