将通用类型分配给Class类型的变量

时间:2018-10-04 19:10:05

标签: java instanceof

// 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 :(得分:1)

您无法检查是否有HashMap<Long,HashMap<String, Semaphore>>的实例。

尽管语法暗示HashMap<Long,HashMap<String, Semaphore>>是一件事,但该类型实际上意味着:

  • 此类型的变量将在运行时保存HashMap(或null)
  • 我希望编译器在我尝试插入或取出不是Long的键时阻止我,而在我尝试插入或取出不存在的任何键时阻止我。 t HashMap,其键和值是该特定类型。

<>之间的位纯粹是编译时间提示。在运行时没有要测试的东西。

提供的地图不为空,您可以检查其中是否包含违反类型约束的键或值。

但是,除了您只能在地图为非空且包含非null键和值的情况下执行此操作外,它不会告诉您它是否为 HashMap<Long,HashMap<String, Semaphore>> < / em>,而是它是HashMap<? extends Long, ? extends HashMap<? extends String, ? extends Semaphore>>

您可以安全地使用此类地图中保存的东西,但不能安全地添加到其中,除非重新添加该地图中已包含的键和值,否则为null。

答案 1 :(得分:0)

编译后,泛型将被删除。
因此,即使这段有效的代码也无法进一步帮助您:

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;
    }

}

因此,您可以使用tClassuClassvClass来执行所需的检查。
但是如上所述,这样做并不是最好的选择。