Java泛型使用的简单介绍

一. 泛型是什么

“泛型”,顾名思义,“泛指的类型”。我们提供了泛指的概念,但具体执行的时候却可以有具体的规则来约束,比如我们用的非常多的ArrayList就是个泛型类,ArrayList作为集合可以存放各种元素,如Integer, String,自定义的各种类型等,但在我们使用的时候通过具体的规则来约束,如我们可以约束集合中只存放Integer类型的元素,如List<Integer> iniData = new ArrayList<>()。

二. 使用泛型有什么好处

以集合来举例,使用泛型的好处是我们不必因为添加元素类型的不同而定义不同类型的集合,如整型集合类,浮点型集合类,字符串集合类,我们可以定义一个集合来存放整型、浮点型,字符串型数据,而这并不是最重要的,因为我们只要把底层存储设置了Object即可,添加的数据全部都可向上转型为Object。 更重要的是我们可以通过规则按照自己的想法控制存储的数据类型。

Java泛型使用的简单介绍

我们以ArrayList为例,假如我们要将本月截至今天的日期放到ArrayList中,如果我们不使用泛型,此时我们定义一个ArrayList.

List monthDays = new ArrayList();

我们向其中加入1号到4号日期

public static List addMonthDays(){ List monthDays = new ArrayList(); monthDays.add(LocalDate.now().withDayOfMonth(1)); monthDays.add(LocalDate.now().withDayOfMonth(2)); monthDays.add(LocalDate.now().withDayOfMonth(3)); monthDays.add(new Date()); return monthDays; }

这样有没有问题?大家也看出来了,当然有,虽然都可以表示日期,但却用了Date,LocalDate,我们调用方法直接打印出来,就是这样

public static void main(String[] args) { List monthDays = addMonthDays(); for(Object day : monthDays){ System.out.println(day); } } 2019-08-01 2019-08-02 2019-08-03 Sun Aug 04 10:27:10 CST 2019

我们肯定不想要这样的结果,我们想要的是

2019-08-01 2019-08-02 2019-08-03 2019-08-04

如果存储的元素类型只是这两种(假如我们知道),这个时候我们就手动判断一下

public static void main(String[] args) { List monthDays = addMonthDays(); for(Object day : monthDays){ if (day instanceof Date){ Date date = (Date) day; System.out.println(LocalDate.of(date.getYear(), date.getMonth(), date.getDay())); }else { System.out.println(day); } } }

这个时候我们就可以达成上述目的了,但大家也知道,这种写法问题问题很大

我们无法控制存储的元素到底是否和日期相关,如我们存储了“1”,65536等非日期,定义的方法也不会报错,但在调用进行类型转换的时候必然会报错;

我们不知道集合中到底存储了哪些类型的元素,比如还有“2019/08/04”这种日期字符串、Java.sql.Date这种类型呢,我们很难保证可以穷尽;

代码过于复杂,太难维护;

这时泛型就提供了很好的解决方案,从源头上就制定好规则,只能添加LocalDate类型,那么上述的问题就都得以解决了。

public static List<LocalDate> addFormatMonthDays(){ List<LocalDate> monthDays = new ArrayList<>(); monthDays.add(LocalDate.now().withDayOfMonth(1)); monthDays.add(LocalDate.now().withDayOfMonth(2)); monthDays.add(LocalDate.now().withDayOfMonth(3)); monthDays.add(new Date());//这个代码在编译期间就无法通过了 return monthDays; }

不仅提高了代码的可读性,一眼即可看出我们存储的是LocalDate类型。同时编译器也可很好的利用该信息,编译期间就可进行类型检查,保证了安全性,在get的时候,无需进行强制类型转换。

三. 泛型类

为使类适应更多的情况,具备更好的扩展性,我们可以将其设置为泛型类,即具有一个或多个类型变量的类,写法如下:

public class ClassName<泛型标识,可以是字母、中文字符等,不过一般用大写英文字符> { private 泛型标识 property; }

对于泛型标识符,一般有一些约定俗称的写法,如果是表示集合的元素类型,一般用字母E,如我们常用的ArrayList,public class ArrayList<E>,我们自定义如下:

//车库 public class Garage<E> { //向车库中添加车 public void add(E car){ //... } }

我们还可以用字符K和V表示关键字和值的类型,如我们常用的HashMap,public class HashMap<K,V>,我们也可以自定义如下:

//映射关系 //K,V: 蔬菜,是否有机; 水果,产地; 服装,类型; 汽车,品牌 public class Mapping<K, V> { private K key; private V value; }

我们还经常用一个字符T表示类型

public class Person<T> { private T t; public Person(T t){ this.t = t; } public void run(){ System.out.println(t); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/c39c48895b533d6647128d11d0c15f2a.html