Effective Java笔记第四章泛型第七节优先考虑类型安全的异构容器

Effective Java笔记第四章泛型

第七节优先考虑类型安全的异构容器

1.泛型最常用于集合,如Set和Map,以及单元素的容器,如ThreadLocal和AtomicReference。在这些用法中,它都充当被参数化了的容器。这样就限制了你每个容器只能有固定数目的类型参数。一般来说,这种情况正是我们想要的。例如:一个Set只有一个类型参数,表示他的元素类型;一个Map有两个类型参数,表示他的键和值类型。

2.有时候会需要更多的灵活性,这时候就有一种方法可以很容易的做到,就是将键进行参数化而不是将容器参数化。然后将参数化的键提交给容器,来插入或者获取值。用泛型系统来确保值的类型与他的键相符。下面我们举个例子:

public class Favorites {

    private  Map<Class<?>, Object> favorites = new HashMap<>();

    public <T> void putFavorite(Class<T> type, T instance) {
        if (null == type) {
            throw new NullPointerException("Type is null");
        }
        favorites.put(type,type.cast(instance));
    }

    public <T> T getFavorite(Class<T> type) {
        return type.cast(favorites.get(type));
    }

    public static void main(String[] args) {
        Favorites favorites=new Favorites();
        favorites.putFavorite(String.class,"Java");
        favorites.putFavorite(Integer.class,0xcafebabe);
        favorites.putFavorite(Class.class,Favorites.class);
        String string = favorites.getFavorite(String.class);
        Integer integer = favorites.getFavorite(Integer.class);
        Class aClass = favorites.getFavorite(Class.class);
        System.out.printf("%s %x %s%n",string,integer,aClass);
    }

}

输出:
Java cafebabe class capter_four.day7.Favorites

1)Favorites实例是类型安全的:当你向他请求String的时候,他从不会返回一个Integer给你。同时他也是异构的(不像普通的Map,他的所有键都是不同类型的,使key-value不受类型限制)。因此,我们将Favorites 称作类型安全的异构容器。
2)注意Map< Class< ? >, Object >中的通配符类型是嵌套的:他不是属于通配符类型的Map的类型,而是Map的键,可以用来赋值,所以每个键都可以有一个不同的参数化类型。
3)value的类型不能是T,不然就指定类型了,由于不确定具体的value类型,所以用Object,之后在取值的时候对他进行了转化。
4)Class.cast方法是java转换操作符用的动态模拟。它只检验他的参数是否为Class对象所表示的类型的实例。如果是,就返回参数;否则就抛出ClassCastException异常。
Class< T >类中的源码:

@SuppressWarnings("unchecked")
    public T cast(Object obj) {
        if (obj != null && !isInstance(obj))
            throw new ClassCastException(cannotCastMsg(obj));
        return (T) obj;
    }

5)Favorites类不能用在不可具体化的类型中,就是说参数Class< T > 不能传入List< String >之类的对象,因为List< String >和List< Integer >共用一个Class对象,就是List.Class。

3.总之,集合API说明了泛型的一般用法,限制你每个容器只能有固定数目的类型参数。你可以通过将类型参数放在键上而不是容器上来避开这一限制。对于这种类型安全的异构容器,可以用Class对象作为键。以这种方式使用的Class对象称作类型令牌。你也可以使用定制的键类型。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值