Присвойте универсальный тип переменной типа Class - PullRequest
0 голосов
/ 04 октября 2018
// I would like to create a variable of Class type and assign a pattern into it like that:
Class clazz = HashMap<Long,HashMap<String, Semaphore>>.class; // does not work!

// I need it in order to be able later use it in .isInstance() expression, like:
if (clazz.isInstance(myVariable)) {
    // do something
}

, потому что обычный «instanceof» не работает ни на типах шаблонов.

С простыми типами (не шаблонными типами) он работает:

Class clazz = Long.class; // this works fine

Какя могу добиться того, что я хочу, это назначить шаблон, а не простой тип?Если это не разрешено в Java, есть ли другой правильный способ проверить, является ли переменная экземпляром типа, определенного как шаблон?

Ответы [ 2 ]

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

Вы не можете проверить, есть ли у вас экземпляр HashMap<Long,HashMap<String, Semaphore>>.

Несмотря на то, что синтаксис подразумевает, что HashMap<Long,HashMap<String, Semaphore>> - это одна вещь, этот тип на самом деле означает:

  • Переменная этого типа будет содержать HashMap (или ноль) во время выполнения
  • И я хочу, чтобы компилятор остановил меня, если я попытаюсь ввести или вынуть ключ, который не является Long и остановит меня, если я попытаюсь вставить или вынуть что-либо, кроме HashMap, чьи ключи и значения относятся к этому конкретному типу.

Бит между <>s это просто подсказка времени компиляции.Там нет ничего, чтобы проверить во время выполнения.

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

Но, кроме того, что вы можете сделать это только в том случае, если карта не пуста и содержит ненулевые ключи и значения, она не сообщает вам, является ли она HashMap<Long,HashMap<String, Semaphore>>, носкорее это HashMap<? extends Long, ? extends HashMap<? extends String, ? extends Semaphore>>.

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

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

Обобщения стираются после компиляции.
Таким образом, даже этот действительный код не поможет вам в дальнейшем:

HashMap<Long, HashMap<String, Semaphore>> map = new HashMap<>();
Class<?> clazz = map.getClass();

clazz будет означать java.util.HashMap «только», а не его обобщения.

О вашем требовании, если случится так, что вам придется написать такой код и, кроме того, проверив типы обобщенных типов:

if (clazz.isInstance(myVariable)) {
    // do something
}

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

Если это не разрешено в Java, есть ли другой способ проверить, является ли переменная экземпляром типа, определенного как шаблон?

Вы можете сохранитьтипы, указанные в универсальном экземпляре путем добавления полей class в универсальный класс.Но поскольку вы используете встроенный тип, вы застряли.
С вашим собственным классом вы можете получить информацию таким образом, например:

public class Foo<T, U, V> {

    private Map<T, HashMap<U, V>> map = new HashMap<>();
    private Class<T> tClass;
    private Class<U> uClass;
    private Class<V> vClass;

    public Foo(Class<T> t, Class<U> u, Class<V> v) {
        this.tClass = t;
        this.uClass = u;
        this.vClass = v;
    }

}

Таким образом, вы можете использовать tClass, uClass, vClass для выполнения необходимых проверок.
Но, как уже было сказано, идти по этому пути, вероятно, не лучшая вещь.

...