Java泛型
你要做一个不动声色的大人了。不准情绪化,不准偷偷想念,不准回头看。去过自己另外的生活。你要听话,不是所有的鱼都会生活在同一片海里。 ——村上春树 《舞!舞!舞!》
Q:什么是泛型?
-
Java泛型本质: 参数化类型
从字面意思就可以看出,就是把“类型变成了参数”,如String类型、Integer类型等都作为参数。
==============================================================================
-
泛型-承担“ 保安 ”的角色
-
Q:泛型如何使用?
1.List mylist1=new ArrayList();//未使用泛型; 2.List mylist2=new ArrayList();//参数化类型;
- 集合类容纳的对象都是Object类的实例。也就是说字符串或整型数据等都能存入List列表中,因为Object类是所有类的父类。
=============================================================================
下面看看未使用泛型和使用了泛型的区别:
- 未使用泛型:
-
字符串数据、整型数据等都能存入List列表中,List列表把这些数据都看作时Object类型,当我们只想取出某种类型
数据时,需要进行强制转换。如上图,字符串强转字符串这个没啥问题,但是整型强转字符串类型就会运行报错,出现
ClassCastException错误(类型不匹配)。
=============================================================================
- 使用泛型:
如上述代码,
指定了传入的数据类型必须是String类型,就像保安检查一样,是String类型的数据才能进来(存入),
如果不是就会被拦截(报错)。把String作为参数,类型参数化,这就是泛型。当然你可以把其他类型作为参数。
=============================================================================
Q:泛型有什么作用?
类型参数——类型实参与类型形参
-
类型参数可以类比Java方法中的形参和实参,类型实参就如我前面举的例子,那类型形参长什么样呢?
-
看下图:API文档中List接口的定义
-
这很显然使用了泛型,但它不是确定的数据类型,这就是类型形参。泛型中使用大写的英文字母来作为类型形参。
-
这里的E是一个类型形参,实际中你可以写成String、Integer等等。
=============================================================================
菱形运算符
List mylist2=new ArrayList();
-
上述代码中,mylist2是List
类型的,显然创建的对象也必须是List
类型的,任何其他类型的参数都会产生编译错误。
Java7增加了一种新的语言特性,称为菱形运算符,上面代码可改写为:
List mylist2=new ArrayList();
泛型通配符
- 无界通配符
- 上界通配符
- 下界通配符
1.代码示例:PrintList方法打印任何类型的列表
public static void PrintList(List list) { for (Object o: list)//增强型for循环打印列表 System.out.println(o + " "); } //The method PrintList(List) in the type PrintList is not applicable for the arguments (List) //不能打印List, List等等,因为它们不是List的子类型(只存储整型的列表不是可存储任何类型的列表的子类)。 //使用通配符(?):表示未知类型,即可以是String类型,也可以是Integer类型等等。 public static void PrintList(List list){}
2/3.代码示例:
class Food {}//食物类 class Fruit extends Food {}//水果类 class Apple extends Fruit {}//苹果类 public class Plate {//盘子类(泛型类) public Plate(T t){item=t;} public void set(T t){item=t;}//放和取操作 public T get(){return item;} private T item; public static void main(String[] args) { //定义水果盘子 Plate p1=new Plate(new Apple());//Error :apple:与水果有继承关系,但:apple:盘子与水果盘子之间没继承关系 //上界通配符,中间表示T及任何T的派生类的类型数据,这个例子中理解为‘这个盘子能装任何水果’,苹果当然没问题 //能装任何水果的盘子与苹果盘子之间就有了继承关系(Plate 是Plate的基类) Plate p1=new Plate(new Apple()); //不能往里存,只能往外取。是水果就能放进来,但编译器并不知道是什么水果,当要对苹果赋值时,编译器找不到。 p1.set(new Fruit()); //Error //读取出来的东西只能存放在Fruit或它的基类里。从水果盘子里来的肯定是水果,或者是食物(基类) Fruit newFruit1=p1.get(); Object newFruit2=p1.get(); Apple newFruit3=p1.get(); //Error //下界通配符,表示T及任何T的基类的类型数据,这个例子中理解为‘这个盘子能装任何食物(水果基类)’。 Plate p2=new Plate(new Fruit()); //不影响往里存,但往外取只能放在Object对象里 p2.set(new Fruit()); p2.set(new Apple()); Apple newFruit4=p2.get(); //Error Fruit newFruit5=p2.get(); //Error Object newFruit6=p2.get(); } }
上界下界参考> https://blog.csdn.net/hello_worldee/article/details/77934244
简单泛型类和接口
public class GenericMemoryCell {//泛型类 public E read() {return Value;} public void write(E x) {Value=x;} private E Value; }
package java.lang //泛型接口,Comparable接口; public interface Comparable { public int compareTo(E other) }
注:参考百度百科及《数据结构与算法分析》