Java 里的泛型简介.
我们在JDK中有时回见到1个类or接口后面跟这1个尖括号.
例如:
java.util.HashMap<K,V>
我们一开始大概知道K,V 大概就是Key和Value的意思, 键值对嘛, 但是不知道这个特性对编程的影响.
其实这个设计Java的泛型问题. 把本文看完就明白了.
一. Java里泛型的定义
在数据结构中, 泛型(generic)这个词代表一种编程思想.
它的意思就是: 不论存储结构如何差异, 都可以令其具有看起来一样的操作方法.
例如 ArrayList 和 LinkList 这两个容器, 它们在内存内的存储结构是完全不同的.
但是它们的操作方法基本上是一样的.
都具有相同的,add() 方法, remove()方法, size()方法等等.
这就是泛型的编程思想.
但是在Java里不能直接操作内存, Java里泛型是另一种定义:
java里泛型用于限制传入容器和接口的数据类型.
二. 容器里的泛型.
我们打开Java JDK API, 查看ArrayList这个类
会见到下面的字眼
java.util
类 ArrayList<E>
ArrayList后面有个尖括号, 里面一个大写E.
其实E代表的是Element的意思, 它告诉我们, ArrayList可以用泛型来限制放入容器里的对象类型.
2.1 假如不使用泛型
假如我们不适用泛型
代码是这样写的:
import java.util.ArrayList;class Student{int id;private String name;public Student(int id, String name){this.id = id;this.name = name;}public String toString(){return this.id + ": " + this.name;}
}public class ArrayList1{public static void main(String args[]){ArrayList arr = new ArrayList();arr.add(new Student(1,"Jack"));arr.add(new Student(2,"Bill"));arr.add(1);arr.add("Jack");Student st = arr.get(1);System.out.println(st);}}
上面的代码中, arr这个容器添加了两个Student对象, 1个integer对象(自动装箱),1个String对象.
但是编译失败
原因在于这行代码:
Student st = arr.get(1);
在JDK API中, get()方法是这样定义的:
get
public E get(int index)
- 返回此列表中指定位置上的元素。
其实上面的定义告诉我们, 可以使用泛型来决定get()方法的返回值类型, 但是如果不使用泛型, 返回的类型是object.
上面用1个Student的引用st 来接收1个Object类型对象, 所以会编译失败.
所以我们需要强制转换, 将出错的代码改为:
Student st = (Student)arr.get(1);
这样就编译通过了.
但是编译信息有两句warning:
Note: ArrayList1.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
它告诉我们这样是不安全的, 因为没有使用泛型, arr容器内还可能有其它的类型的对象.
一旦我把上面的get方法里的参数从1改成2, 则会发生转会失败, 抛出异常..
2.2 使用泛型:
我们可以在定义1个容器时使用泛型, 方法很简单, 就是在容器类名后面加上尖括号,后面写上你要放入的对象类名.
例如:
Arraylist<Student> arr = new ArrayList<Student>();
修改后的代码如下:
import java.util.ArrayList;class Student{int id;private String name;public Student(int id, String name){this.id = id;this.name = name;}public String toString(){return this.id + ": " + this.name;}
}public class ArrayList2{public static void main(String args[]){ArrayList<Student> arr = new ArrayList<Student>();arr.add(new Student(1,"Jack"));arr.add(new Student(2,"Bill"));//arr.add(1);//arr.add("Jack");Student st = arr.get(1);//Student st = (Student)arr.get(1);System.out.println(st);}}
上面的 get()方法已经不需要强制转换了.
值得注意的是, 当使用了泛型以后, 上面的arr容器就不能再放入除Student对象之外的其他类型元素. 否则会报错!
三. 接口里的泛型.
我地再一次打开JDKAPI, 看看Comparable接口的定义:
ava.lang
接口 Comparable<T>
-
类型参数: -
T
- 可以与此对象进行比较的那些对象的类型
然后再看看Comparable里面最重要的方法:
int
|
compareTo(T o) 比较此对象与指定对象的顺序。 |
里面都有1个T, 意思也是可以利用泛型来指定传入Comparable接口里方法的参数类型:
3.1 假如不使用泛型:
如果不使用泛型, 那么使用实现了Comparable接口的对象里的comparaTo方法里就能接受各种类型的对象, 必须使用强制转会:
例子:
import java.lang.Comparable;class Student implements Comparable{int id;private String name;public Student(int id, String name){this.id = id;this.name = name;}public String toString(){return this.id + ": " + this.name;}public int compareTo(Object o){Student st = (Student)o;return this.id - st.id;}
}public class Comparable1{public static void main(String args[]){Student jack = new Student(1,"Jack");Student bill= new Student(2,"Bill");System.out.println(bill.compareTo(jack));}
}
例如上面的例子
类Student 实现了Comparable接口, 重写comparaTo时的参数必须是对象Object
内容里还必须强制转会:
Student st = (Student)o;
这样写虽然看起来ok, 但是实际上也不安全
因为这样写, Student对象调用compareTo方法时就能放入各种类型的参数.
编译时是无错的,但是执行时就有可能转换失败了.
3.2 假如使用泛型.
接口使用泛型的方法也很简单:
只需要在接口名后面加上<参数类名>就ok
修改后的例子:
import java.lang.Comparable;class Student implements Comparable<Student>{int id;private String name;public Student(int id, String name){this.id = id;this.name = name;}public String toString(){return this.id + ": " + this.name;}public int compareTo(Student s){return this.id - s.id;}
}public class Comparable2{public static void main(String args[]){Student jack = new Student(1,"Jack");Student bill= new Student(2,"Bill");System.out.println(bill.compareTo(jack));//System.out.println(bill.compareTo("jack")); compile error}
}
上面修改后, 重写的compareTo方法参数就应该指定为Student类.
而且不能将其他类型对象作为参数调用, 否则编译出错.
四. 使用泛型的意义
通过上面的例子, 我们可以得出使用java泛型 有如下好处:
1.避免强制转换的代码
2.限制传入容器的对象类型 和 接口方法参数的类型
3.避免了编译通过, 但是因为强制转换失败而执行出错的情况. 令java程序更加安全健壮.
Java 里的泛型简介.相关推荐
- 【Java 泛型】泛型简介 ( 泛型类 | 泛型方法 | 静态方法的泛型 | 泛型类与泛型方法完整示例 )
文章目录 一.泛型简介 二.泛型类 三.泛型方法 四.静态方法的泛型 五.泛型类与泛型方法完整示例 一.泛型简介 泛型 可以 简单理解为 参数化类型 , 主要作用在 类 , 方法 , 接口 上 ; j ...
- Java 里的thread (线程)简介
在Java里 thread 就是线程的意思. 说到线程的概念, 自然离不开另外两个词: 程序和进程. 从最基本的程序讲起: 一. 什么是程序(Program) 所谓程序, 就是1个严格有序的指令集合. ...
- java 里 泛型中 T代表什么类型
java 里 泛型中 <T>代表什么类型呀? public <T> List<T> find(String sql, Class<T> entityCl ...
- 2015第22周六Java反射、泛型、容器简介
Java的反射非常强大,传递class, 可以动态的生成该类.取得这个类的所有信息,包括里面的属性.方法以及构造函数等,甚至可以取得其父类或父接口里面的内容. obj.getClass().getDe ...
- Java里的容器 Collection 简介
容器也是Java面试经常问到的问题. 也是Java编程的其中1个难点. 在一篇文章中很难全部讲清楚, 我打算分几篇逐步介绍. 一. 什么是容器 1.1 容器的定义 Java里的容器的定义很简单: ...
- JAVA里面的int类型 和Integer类型,有什么不一样
JAVA里面的int类型 和Integer类型,有什么不一样 原创 2013年09月04日 23:15:11 标签: java / 2120 编辑 删除 JAVA里面的int类型 和Integer类型 ...
- JAVA中parameterized,Java中与泛型相关的接口 之 ParameterizedType
在阅读本文之前可以先阅读以下三篇,以便对Java中的泛型有一个全局的认识: 简介 ParameterizedType是Type的子接口,表示一个有参数的类型,例如Collection,Map等.但实现 ...
- Java中创建泛型数组
Java中创建泛型数组 使用泛型时,我想很多人肯定尝试过如下的代码,去创建一个泛型数组 T[] array = new T[]; 当我们写出这样的代码时编译器会报Cannot create a gen ...
- Java中的泛型 --- Java 编程思想
前言 我一直都认为泛型是程序语言设计中一个非常基础,重要的概念,Java 中的泛型到底是怎么样的,为什么会有泛型,泛型怎么发展出来的.通透理解泛型是学好基础里面中非常重要的.于是,我对<Ja ...
最新文章
- java获取json中的某个值_接口测试之json中的key获取
- Linux命令(2)—— 如何切换当前目录
- 从OpenFOAM的源码中查找信息
- LeetCode 1209. 删除字符串中的所有相邻重复项 II(栈)
- 桌面应用程序 azure_如何在Azure中连接我们的C#应用​​程序
- dp线和hdmi区别_各类视频线有什么区别?应该怎么选呢?
- 判断二进制半整数_牛客网
- samba 部署和优化
- matlab数字图像处理常用操作
- 微信公众号调用扫一扫
- 全面了解三极管——三极管基本参数2
- hp打印机计算机接口,老司机操作电脑连接惠普打印机提示无法识别UsB端口的办法?...
- Java:javax.mail通过163服务器发送邮件
- linux 打印进程日志,Linux系统日志管理:(2)进程统计日志
- 马化腾和朱啸虎互怼之后,摩拜ofo合并可能性基本为零
- 高盐废水处理工艺——料液精制与除杂
- 仿京东轮播的广告展示栏
- javascript 数据类型与类型转换
- 在Google使用Borg进行大规模集群的管理 7-8
- 网站页面优化必然趋势—WebP 图片!