`
zddava
  • 浏览: 240829 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

深入了解Java泛型(五) -- 类型令牌

阅读更多
可以考虑下这样的场景:假设我的一个应用中有很多类都是"无状态"的,并且实例化一个这种类是很费资源的,更糟的是发现这些类没有一个是单例的,这个时候可以考虑在外部编写一个单例的缓存,使用这个缓存来维护这些类的实例。

考虑到类型安全性,我想使用泛型去实现这个缓存,但是泛型一般只能有有限的类型参数,比如Set和List有1个,Map有2个,这个时候就可以考虑不将缓存泛型化,而将缓存的键泛型化。说了这么多还是看看具体的代码吧。

public class SingletonClassCache {
	private static Map<Class<?>, Object> cache = new HashMap<Class<?>, Object>();

	public static synchronized <T> void put(T t) {
		cache.put(t.getClass(), t);
	}

	public static synchronized <T> T get(Class<T> clazz) {
		return clazz.cast(cache.get(clazz));
	}
}


这个类很简单,SingletonClassCache并没有泛型化,而是把内部的静态成员cache的键变成了Class<?>类型,这样就可以通过它的两个泛型方法去实现安全的缓存单例了。

public class TypeTokenTester {

	public static void main(String[] args) {
		String s = new String("string");
		SingletonClassCache.put(s);
		Integer i = new Integer(1);
		SingletonClassCache.put(i);

		System.out.println(s == SingletonClassCache.get(String.class));
		System.out.println(i == SingletonClassCache.get(Integer.class));
	}

}


运行结果当然都是true,说明引用指向的都是同一个对象。

上边的这种用法就是所谓的类型令牌了。通过这种方式,可以增加泛型的灵活性,但是这种方式也有一个很大的缺点。比如List<String>这种泛型类型的对象是不能通过类型令牌保存的,因为泛型类型在运行时是会擦除泛型信息的,List<String>.class是会报出语法错误的,这样其实也更安全,因为List<String>和List<Integer>其实用的是同一个Class对象。
分享到:
评论
1 楼 wangluo19 2011-07-06  
读了博主的深入泛型1到5这五篇文章,加深了我对泛型的理解;
理解了?表示的含义
理解了泛型类,实例化类的时候会替换泛型参数
理解了泛型方法,泛型方法的替换与泛型类相同,注意到了E对于泛型来讲是个符号,是在方法的static后面声明的。

博主文章给力啊

相关推荐

Global site tag (gtag.js) - Google Analytics