闲谈:
说到泛型,大部分人肯定都不陌生,在我学习泛型之前,对他的概念是一个T类型的对象,它可以指代各种类型。没错,可以这么理解,但是其中又有很多值得思考的问题,泛型跟Object有什么区别,泛型的用法等等,这些都是值得我们去深思的一个问题。
以前一直都想着利用泛型来好好装逼,但是因为技术不足,也可以说是人懒,对java的理解没有这么深刻,学习的过程中总觉得特别困难,一直都处于一知半解的状态,最近在公司项目开发过程中,发现框架里面有好多东西都运用了泛型优化代码,感觉也差不多是再对泛型进一步学习的时候了。
说一说我印象最深刻的几行代码,是用来简化Android控件绑定的。
|
|
这个是写在了基类的Activity中作为所有Activity的父类,在子类中findViewById的写法就变成了如下:
对比android原生自带的findViewById是不是直接取消了类型的强转,这如果在Activity很多的情况下是可以少很多代码和时间的。
直接取消掉了类型的强转,是不是简单了许多。好了,这么一个强大的东西,是时候好好学习一波了。
一、泛型的概念
泛型实现了参数化类型的概念,使代码可以应用于多种类型。在你创建参数化类型的一个实例时,编译器会为你负责转型操作,并且保证类型的正确性。
二、泛型的使用
普通泛型
有许多原因促成了泛型的出现,而最引人注目的一个原因就是为了创造容器类。基本上所有的程序运行时都要求你持有一大堆对象,所以容器类算得上最具重用性的类库之一。
接下来我们可以通过对比来裂解一下泛型作为容器类的好处
这个类可以明确指定其持有的对象类型,但他的重用性就不怎么样了。试想一下如果我们也有一个BModel同样需要放在这样一个容器持有类中。再重新写一个类代码就显得太多太杂了,毕竟要实现的功能是差不多的。
现在Holder 可以存放各种不同类型的对象了,因为所有的java类都是Object的子类,java支持向上向下转型的。所以这个代码可以作为任意类型的容器了。
有些情况下,我们确实希望容器能够同时持有多种类型的对象,但是,通常而言,我们只会使用容器来存储一种类型的对象。泛型的主要目前之一就是用来指定容器要持有什么类型的对象,而由编译器来保证类型的正确性。
因此,与其使用Object,我们更喜欢暂时不指定类型,而是稍后再决定具体使用什么类型。
现在,当你创建Holder3对象时必须指明想持有什么类型的对象,将其置于尖括号内。然后你就能在Holder3存入该类型。
并且,在你从Holder3取出它的持有对象时,自动就是正确的类型。
现在我们来试试元组,持有多种不同类型。
现在我们拥有了一个可以持有两个对象的元组了,如果我们再需要三个对象的元组。
小结
不知道有没有人注意到 Holder3<Model> h3 = new Holder3(new Model());在初始化这个对象持有类的时候我们指明了我们想要的类型。然后编译器自动帮我们编译成了这个类型。也就是说编译器在执行h3.get();的时候它是已经明确知道了h3.get()的类型了,并自动进行了强转。而Model model = (Model) h2.get();这个,当编译器在执行这一句的时候他还不知道h2.get()到底是什么类型,最后我们告诉它,要强转成Model以适配model这个实例化对象,来进行存储。
接下来讲讲泛型接口
泛型接口
|
|
泛型也可以应用于接口,例如生成器,作为工厂方法设计模式的一种应用。
泛型方法
只需要在方法返回类型前加泛型参数就可以啦,看代码
通过泛型方法返回泛型类型实例
使用泛型统一传入的参数类型
学习完泛型我们可以知道,泛型并非只用一个T字幕来表达,它的命名风格基本为大写的英文字母,比如ABCDEFG... 泛型可以通过继承来定义上限。可以实现泛型的方法,泛型类,泛型接口,可以定义泛型数组泛型嵌套等一系列使用方法。
它跟Object的区别:是没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
参考自网易博客北漂的小羊
java编程思想第四版 泛型篇
By Xiaolong:You have a dream,you got to protect it!