需要提前知道的知识:
- Class类:
Class类是Java机制中的一个特殊类,我们可以通过它获取其他类的属性类型、名称、方法、基类等等信息。为什么可以通过它去获取其他类的信息呢?因为Java中设定了每个类都有这么一个Class类对象,是JVM为我们创建好的,其中一种常见的获取方式就是通过某个类的对象的.getClass()方法获取,获得某个类的Class对象后,我们就可以通过Class类提供的一些方法去读取这个类的信息了,提供的方法比如getFields()、getMethods()等方法。
其他获取Class对象的方法:Class.forName(“完整的包路径+类名”)、类名.class
- Class<T>:
如果只是Class,那么一个Class对象只能表示一个具体的Class类型,比如Class class = A.class; 此时class对象只能是类A的Class对象,但是如果是Class<T>,其实就是和普通的List<T>一样,它可以是任意类型,比如用Class<T>作为传参,那么你可以传Class<String>,也可以是Class<Long>。类Class本身是被泛化了的。 - 异构容器:
理解什么是异构容器,可以拿非异构容器Map<K,V>来理解,Map只能指定key为一种类型,同时只能指定value为一种类型,而异构容器指的是有这么一种Map,它的key可以是任意类型,比如第一个key是String类型的,第二个是Long类型的。有什么好处呢?灵活!让key-value不受类型限制。
创建异构容器
创建异构容器的关键就在于,使用Class<T>(这种写法也被叫做类型令牌)来作为Map的key,比如:
public class SpecialMap {
private Map<Class<?> , Object> data = new HashMap<>O
public <T> void put (Class<T> type, T instance) {
data.put(Objects.requireNonNull(type), instance);
}
public <T> T get(Class<T> type) {
return type.cast(data.get(type)) ;
}
}
Class<?>和T<?>一样,可以用于赋值,但是不能增删,这里作为key只赋值,满足使用需要。
value的类型不能也是T了,不然就指定类型了,由于不确定具体value的类型,这里使用Object类型,所以后面取值需要转化一下类型(其实因为在get时指定了类型,不会发生类型转化出错的风险)。
cast 方法是 Java 的转换操作符的动态模拟。 它只检验它的参数是否为 Class 对象所表示的类型的实例。 如果是,就返回参数;否则就抛出 ClassCastException 异常。
参数Class<T>不能传入List<String>之类的对象,因为List<String>和List<Long>的Class对象都是List.class,所以传入这类对象会编译不通过。
异构容器的核心要点和大致的思路就是这些,这里的Class<T>也可以是自己定制的键类型。