泛型总结
泛型
参与了孤尽大大的DIY班,这一期的主题时泛型,之前没有深入研究过泛型,于是有了此篇的总结。
1.简单的泛型类和接口
public class GenericMemoryCell<AnyType>{ public AnyType read(){ return storedVal; } public void write(AnyType x){ storedVal = x; } private AnyType storedVal; }
public interface Comparable<>{ public int comparaTo(AnyType other); }
从基础的泛型可以看出,限制了类和接口的参数的类型。这样一个直接的好处就是,时以前只有在运行时报告的错误,如今现在可以在编译时报错。
2.菱形运算符
//通过<>可以省略,自动匹配要生成的类的type GenericMemoryCell<Integer> m=new GenericMemoryCell<>();
3.带有限制的通配符
现在场景:totalArea是一个计算图形面积的静态方法,Shape是一个父类,Square,Circle继承了Shape的父类。
public static double TotalArea(Colletion<Shape> arr){ double total=0; for(Shap s:arr){ if(s!=null) total+=s.area(); } return total; }
问题是,如果是,方法中传入,Colletion。编译通过,但是产生运行时错误。为了解决这个问题,java5采用了通配符表示参数类型的子类或者超类。Collection ,T IS-A Shape 。
public static double TotalArea(Colletion<?extends Shape> arr){ double total=0; for(Shap s:arr){ if(s!=null) total+=s.area(); } return total; }
4.泛型方法
定义泛型方法时,必须在返回值前边加一个,来声明这是一个泛型方法,持有一个泛型T,然后才可以用T作为方法返回值
泛型方法要求的参数是Class类型,而Class.forName()方法的返回值也是Class,因此可以用Class.forName()作为参数。其中,forName()方法中的参数是何种类型,返回的Class就是何种类型。在本例中,forName()方法中传入的是User类的完整路径,因此返回的是Class类型的对象,因此调用泛型方法时,变量c的类型就是Class,因此泛型方法中的泛型T就被指明为User,因此变量obj的类型为User。
当然,泛型方法不是仅仅可以有一个参数Class,可以根据需要添加其他参数。
为什么要使用泛型方法呢?因为泛型类要在实例化的时候就指明类型,如果想换一种类型,不得不重新new一次,可能不够灵活;而泛型方法可以在调用的时候指明类型,更加灵活。
public static <T> boolean contains(T [] arr,T x){ for(T val:arr){ if(x.equals(val)) return true; } return false; }
5.类型界限
我们想编写一个finMax的程序,比较的AnyType必须是实现comparable才可以比较。下面的这种方法是不行的
public static <AnyType> AnyType findMax(AnyType [] arr){ int maxIndex=0; for(int i=0;i<arr.length;i++){ if(arr[i].compareTo(arr[maxIndex])) maxIndex=i; } return arr[maxIndex]; }
改写泛型,需要比较的泛型是可以比较的。所以就有
public static >
假设Shape实现了Comparable,Square继承了Shape,Square所继承的泛型是Comparable,并不是Comparable,但是这样也是可以的。所以,可以写成以下格式:
public static <AnyType extends Comparable<? super AnyType>> AnyType findMax(AnyType [] arr){ int maxIndex=0; for(int i=0;i<arr.length;i++){ if(arr[i].compareTo(arr[maxIndex])) maxIndex=i; } return arr[maxIndex]; }
6.类型擦除
因为,泛型是java语言中的成分,而不是虚拟机中的结构。所以泛型类需要经过虚拟机的类型擦出而变成非泛型类。
编译器生成一个与泛型类名相同的原始类。类型变量使用它们原先的类型界限来代替。
7.对于泛型的限制
由于类型擦除的存在,所以必须遵从以下规则:
1.基本类型不能做类型参数
2.instanceof检测和类型转换工作只对原始类型进行。
这句话的理解,就是编译时检测,只对原始类型有用,进行转换之后就不管用了。
GenericMemoryCell<Integer> cell1=new GenericMemoryCell<>(); cell1.write(4); Object cell=cell1; GenericMemoryCell<String> cell2=(GenericMemoryCell<String>) cell; String s=cell2.read;
3.在一个泛型类中,static方法和static域均不可引用类型变量,因为再类型擦出后,类型变量就不存在了。
4.泛型类型的实例化
//非法,如果T是一个类型变量 T obj=new T(); T [] arr=new T[10]
5.参数化类型的数组
如下方案例,正常情况,存在类型检查,但是类型擦除之后,cell和数组arr里面的内容同样都是GenericMemoryCell。只有在实际存储的时候会出现,ClassCastException错误。
GenericMemoryCell<String> [] arr= new GenericMemoryCell<String> [10]; GenericMemoryCell<Integer> cell1=new GenericMemoryCell<>(); cell1.write(4); Object [] arr2=arr; arr2[0]=cell String s=arr2[0].read();
8.函数对象
定义一个没有数据而只有一个方法的类,并传递该类的一个实例。事实上,一个函数通过将其放在一个对象内部而被传递,这样的对象叫做函数对象。
public static <T> T findMax(T [] arr,Comparator<? super T> cmp){ int maxIndex=0; for(int i=0;i<arr.length;i++){ if(cmp.compare(arr[i], arr[maxIndex])>0) maxIndex=i; } return arr[maxIndex]; } class CaseInsensitiveCompare implements Comparator<String>{ public int compare(String lhs,String rhs){ return lhs.compareToIgnoreCase(rhs); } } class TestProgram{ public static void main(String [] args){ String [] arr={"ZEBRA",“ali”,"arc"} System.out.println(findMax(arr,new CaseInsensitiveCompare())); } } //输出:ZEBRA最后
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
带你搭一个SpringBoot+SpringData JPA的环境
前言 只有光头才能变强。 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 不知道大家对SpringBoot和Spring Data JPA了解多少,如果你已经学过Spring和Hibernate的话,那么SpringBoot和SpringData JPA可以分分钟上手的。SpringBoot和SpringData JPA的好处我就不说了,当时我学习的时候也粗略做过笔记,有兴趣的同学可以去看看 SpringBoot就是这么简单 SpringData JPA就是这么简单 其实我在学完SpringBoot和SpringData JPA了之后,写过一个小Demo,但一直没发出来而已(懒)。而最近要写毕业设计的一个管理模块(CRUD),并且我又没写过相关SpringBoot和Sp
- 下一篇
深度学习最佳图书推荐(2019版)
你是否希望深入学习深度学习?如果你有这方面的意愿,请不要辜负我的整理工作,这是2019年最佳机器学习和深度学习书籍清单: ·Deep Learning by Ian Goodfellow, Yoshua Bengio, Aaron Courville ·Grokking Deep Learning by Andrew W.Trask ·Deep Learning with Pythonby Francois Chollet ·Hands-On Machine Learning with Scikit-Learn and TensorFlowby Aurélien Géron ·Reinforcement Learning: An Introduction (2nd Edition)by Richard S. Sutton, Andre
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS关闭SELinux安全模块
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Mario游戏-低调大师作品