欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java的泛型

程序员文章站 2024-03-15 12:28:35
...

    泛型不是啥新特性了,04年的java1.5就推出了,除非对java的学习只限于旧版的java教程或者听大学老师讲的老课本,自己用ArrayList这类容器的时候多少会了解的。这里我写一点我自己的理解。

    多态也是java的一个特性了,说到多态就要扯上塑造型和下塑造型。比如spring的控制反转,注入其实用的就是上塑造型(避免模块和服务耦合嘛)……其实上塑造型没什么安全隐患,最让人头疼的是下溯造型了,比如A、C都实现了接口B,而把B强制转化回原本的类型就很头疼了,打个不恰当的比方就像段正淳那一帮孩子,完全不知道哪个是哪个了。因为如果不正确的强制转换,会抛出异常,这个又是编译期不能检查出来的。如果用反射找Object的真是类型然后用RTTI来检测类型,又不是很方便,而直接强制类型转换很可能导致安全隐患。

    由此可见,矛盾就在于:强制转换要事先知道具体类型。解决这个问题的办法就是型。

    一句话概括型就是:数据类型当参数。泛型的实质是在编译的时候可以检查类型安全,也就是说强制转换都是自动隐式的,所以上面的安全隐患就不用咱操心了。

    比如 class A<T>,实质就是声明了一个没有任何限制泛型类T。实质就是<T extends Object>。

    这里有两个关键词extends和super,但它与继承和超类没什么必然联系,一般更喜欢称之为上界和下界,其实是对型类的一个限制。

    拿集合类举例, class A<T extends Collection>意思就是说T必须实现Collection,这样你传入ArrayList就可以,但你传入Sting啊Integer这类东西就会出错。同理super就是限制下界,说白了就是T的子类或者实现类必须有这个类,其实用集合的闭区间来理解上界和下界就不会觉得这两个关键词很生僻了。

    为了理解方便,我举一个排序的例子:

public static <T extends Comparable<? super T>> void sort(T[] a) {

    我们知道,排序算法应用在自己定义的类上是很方便的,但是一个类写一个排序算法是很不方便。我这个例子就能限制,给这个方法传入一个Object数组糊弄它肯定是不好使滴……其实使用泛型可以实现复用并避免不必要的错误,因为这个例子是必须是实现Comparable接口的类才可以用这个方法进行排序。这样的sort方法不是很方便么?

    那问号又是啥意思?这个就是通配符啦。它是为了避免把某些东西限定死。这里我再举一个例子: 

Demo<Collection> demo = new Demo<ArrayList>(new ArrayList());

    Demo类的定义:

class Demo<T extends Collection> {...

    这个是不能通过编译的,为什么呢?因为demo已经限制死必须是Collection了,Collection的子类是不可以的。要真是这样,那还真没用Object强制转换方便呢……所以这里才要用到通配符。

    对上面的代码加上一点修改: 

Demo<? extends Collection> demo = new Demo<ArrayList>(new ArrayList());

    '? extends Collection'的意思就是任何类,只要下限是Collection都没问题。

    怎么样?这段代码不用泛型实现还是挺麻烦的吧?其实你可以用反射和RTTI试试,如果把上面的sort方法用getClass()来获得类型,强制转换时再用instanceOf判断,代码量足够让人头疼死。

    可能我对泛型的理解还不够位,欢迎补充。


转载于:https://my.oschina.net/tdONEmadao/blog/223186