乱读天书, 不求甚解
周祎骏的个人云笔记
Toggle navigation
乱读天书, 不求甚解
主页
Linux:系统配置
Linux:用户管理
Linux:优化排错
Linux:进程调度
Linux:文件系统
Linux:网络
Linux:系统服务
Linux:安全
Linux:内核
容器:Docker
容器:containerd
容器编排:Kubernetes
IAC:Terraform
大数据:Hadoop
大数据:Zookeeper
大数据:Hbase
消息队列:rsyslog
消息队列:kafka
数据库:MySQL
数据库:MongoDB
搜索引擎:Elasticsearch
时序数据库:OpenTSDB
网站服务:Nginx
编程:Bash
编程:Perl
编程:Python
编程:C
编程:JAVA
编程:Rust
版本控制:gitlab
知识管理:docusaurus
常用小工具
关于我
标签
JAVA 3.01 细谈泛型
2018-08-21 10:50:20
66
0
0
admin
> 泛型的实现与限制 #泛型如何实现 泛型功能是编译器实现的,在jvm虚拟机里没有泛型这个概念,记住这一点,会理解泛型的很多限制 > 假设ArrayList<company> 泛型其实就是编译器在ArrayList的入口做检查,拒绝非company对象 在ArrayList出口做强制转换,把返回的值都转换成company对象 而在程序中,其实都是object对象 **一些限制:** 在泛型类的代码中不能对泛型对象做一些需要知道这个对象是什么对象的操作,比如: ``` T a = new T(); //不可以 ``` 一个容器如果使用泛型,表示这是一个某某泛型的容器,这时候不能把其它类型的容器赋值给这个容器,即使有依赖关系也不行 ``` import java.util.*; public class test{ public static void main(String[] args){ ArrayList<fruit> a = new ArrayList<fruit>(); //ArrayList<fruit> b = new ArrayList<apple>(); 不可以 a.add(new apple());//可以 } } class fruit {} class apple extends fruit {} ``` *** #泛型类和泛型方法的实现 在能使用泛型方法代替的场景下,尽量避免使用泛型类 ``` import java.util.*; public class test{ public static void main(String[] args){ classA a = new classA(); classB b = new classB(); Holder1<classA,classB> h1 = new Holder1<classA,classB>(a,b); System.out.println(h1.geta()+" and "+h1.getb()); Holder2 h2 = new Holder2(); h2.get_class_name(a); } } class classA {} class classB {} class Holder1<A,B> {//泛型类 private A a; private B b; public Holder1(A a,B b){ this.a = a; this.b = b; } public A geta() { return a;} public B getb() { return b;} } class Holder2 { public <T> void get_class_name(T a) { //泛型方法 System.out.println(a.getClass().getName()); } } ``` *** #泛型的边界(用在编写泛型类的时候) 因为泛型对象在内部都是Object 对象,所以我们只能做Object能做的事情。 但是如果我们说明这个泛型类只接受某个对象ClassA或者ClassA的子类,那么我们就能确定这个泛型对象起码是一个ClassA对象,我们就可以对其做一些ClassA能做的操作。 ``` import java.util.*; public class test{ public static void main(String[] args){ classA a = new classA(); Holder<classA> h1 = new Holder<classA>(a); h1.run_f(); } } class classA { public void f(){ System.out.println("hello world"); } } class Holder<T extends classA> { private T a; public Holder(T a) {this.a = a;} public void run_f() {a.f();} } ``` #泛型的通配符(在使用泛型类的时候) ##<? extends T> * T类型或者T的子类都可以 ``` ArrayList<? extends fruit> a = new ArrayList<fruit>(); ArrayList<? extends fruit> b = new ArrayList<apple>(); ``` * 可以从该容器读元素(读出来是T类型),不可以写入新元素 > 因为系统不知道容器中的泛型是什么,如果是一个ArrayList<apple>而你要加一个ArrayList<banana>就出问题了 *** ##<? super T> * T类型或者T的父类都可以 * 可以添加元素,只能返回Object对象作为元素 *** ##<?> * 不能读不能写 * 在特殊情况下用来捕获具体类型 > 如果一个方法的参数是一个容器,而这个容器使用了泛型,我们想要知道这个泛型是什么类型,就需要用到如下代码 ``` import java.util.*; public class test{ static <T> void hold_what(Holder<T> h){ //编写泛型的时候 T t = h.get(); System.out.println(t.getClass().getName()); } static void wrap(Holder<?> h){ //使用泛型的时候,接受任何泛型的Holder容器 hold_what(h);//这个时候编译器已经知道了具体是什么泛型 } public static void main(String[] args){ ClassA a = new ClassA(); Holder<ClassA> h = new Holder<ClassA>(a); wrap(h); } } class ClassA {} class Holder<T> { private T a; public Holder(T a){ this.a = a; } public T get() { return a;} } ```
上一篇:
JAVA 3.00 泛型和容器
下一篇:
JAVA 4.00 接口
文档导航