我们在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 里的泛型简介.相关推荐

  1. 【Java 泛型】泛型简介 ( 泛型类 | 泛型方法 | 静态方法的泛型 | 泛型类与泛型方法完整示例 )

    文章目录 一.泛型简介 二.泛型类 三.泛型方法 四.静态方法的泛型 五.泛型类与泛型方法完整示例 一.泛型简介 泛型 可以 简单理解为 参数化类型 , 主要作用在 类 , 方法 , 接口 上 ; j ...

  2. Java 里的thread (线程)简介

    在Java里 thread 就是线程的意思. 说到线程的概念, 自然离不开另外两个词: 程序和进程. 从最基本的程序讲起: 一. 什么是程序(Program) 所谓程序, 就是1个严格有序的指令集合. ...

  3. java 里 泛型中 T代表什么类型

    java 里 泛型中 <T>代表什么类型呀? public <T> List<T> find(String sql, Class<T> entityCl ...

  4. 2015第22周六Java反射、泛型、容器简介

    Java的反射非常强大,传递class, 可以动态的生成该类.取得这个类的所有信息,包括里面的属性.方法以及构造函数等,甚至可以取得其父类或父接口里面的内容. obj.getClass().getDe ...

  5. Java里的容器 Collection 简介

    容器也是Java面试经常问到的问题.  也是Java编程的其中1个难点. 在一篇文章中很难全部讲清楚, 我打算分几篇逐步介绍. 一.  什么是容器 1.1 容器的定义 Java里的容器的定义很简单: ...

  6. JAVA里面的int类型 和Integer类型,有什么不一样

    JAVA里面的int类型 和Integer类型,有什么不一样 原创 2013年09月04日 23:15:11 标签: java / 2120 编辑 删除 JAVA里面的int类型 和Integer类型 ...

  7. JAVA中parameterized,Java中与泛型相关的接口 之 ParameterizedType

    在阅读本文之前可以先阅读以下三篇,以便对Java中的泛型有一个全局的认识: 简介 ParameterizedType是Type的子接口,表示一个有参数的类型,例如Collection,Map等.但实现 ...

  8. Java中创建泛型数组

    Java中创建泛型数组 使用泛型时,我想很多人肯定尝试过如下的代码,去创建一个泛型数组 T[] array = new T[]; 当我们写出这样的代码时编译器会报Cannot create a gen ...

  9. Java中的泛型 --- Java 编程思想

    前言 ​ 我一直都认为泛型是程序语言设计中一个非常基础,重要的概念,Java 中的泛型到底是怎么样的,为什么会有泛型,泛型怎么发展出来的.通透理解泛型是学好基础里面中非常重要的.于是,我对<Ja ...

最新文章

  1. java获取json中的某个值_接口测试之json中的key获取
  2. Linux命令(2)—— 如何切换当前目录
  3. 从OpenFOAM的源码中查找信息
  4. LeetCode 1209. 删除字符串中的所有相邻重复项 II(栈)
  5. 桌面应用程序 azure_如何在Azure中连接我们的C#应用​​程序
  6. dp线和hdmi区别_各类视频线有什么区别?应该怎么选呢?
  7. 判断二进制半整数_牛客网
  8. samba 部署和优化
  9. matlab数字图像处理常用操作
  10. 微信公众号调用扫一扫
  11. 全面了解三极管——三极管基本参数2
  12. hp打印机计算机接口,老司机操作电脑连接惠普打印机提示无法识别UsB端口的办法?...
  13. Java:javax.mail通过163服务器发送邮件
  14. linux 打印进程日志,Linux系统日志管理:(2)进程统计日志
  15. 马化腾和朱啸虎互怼之后,摩拜ofo合并可能性基本为零
  16. 高盐废水处理工艺——料液精制与除杂
  17. 仿京东轮播的广告展示栏
  18. javascript 数据类型与类型转换
  19. 在Google使用Borg进行大规模集群的管理 7-8
  20. 网站页面优化必然趋势—WebP 图片!

热门文章

  1. optee HSM的实现
  2. [gic]-ARM gicv3/gicv4的详细介绍-2020/08
  3. Raft 集群成员变更、日志压缩、客户端交互
  4. 去除cpp中注释的小程序
  5. python全球购代码_理解python的unicode字符串
  6. 进程间通信——命名管道
  7. JAVASE_File类(实践)——目录拷贝
  8. deedeedee crazy 寒假逆向生涯(11/100)
  9. FSD键盘钩子框架参考爱写驱动的女装大佬
  10. MySQL主从复制Windows实现