二、JavaSE_集合(泛型)
泛型
一、泛型的概述
1.初步了解
首先,我们来看什么是泛型?
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 List list = new ArrayList(); //没有泛型约束 2 List<String> list = new ArrayList<String>();//有泛型约束
第一行代码,没有进行泛型约束,也就是list可以存储的类型是Object。那么这样会存在安全隐患,接下来,我们会谈谈安全隐患的问题。
第二行代码,就是有泛型进行约束的,也就是说第二个list当中只能存放String类型的数据。注:jdk1.7以后,也可以这样定义:List<String> list = new ArrayList<>();也就是后面的类型可以不写。
我们来看Collection的API
E代表的是元素(Element)
其中那个E就代表泛型。
2.泛型的好处
- 提高了安全性(将运行期的错误转换到编译期)
- 省去强转的麻烦
3.泛型解决安全隐患
安全隐患的问题,通过代码来看:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /** 2 * 早期的Object类型可以接收任意的对象类型, 3 * 但是在实际的使用中,会有类型转换的问题。也就存在这隐患,所以Java提供了泛型来解决这个安全问题。 4 */ 5 public class Demo { 6 public static void main(String[] args){ 7 //创建工具类对象 8 Tool tool = new Tool(); 9 //往工具类设置狗类 10 tool.setObject(new Dog("金毛","金黄色")); 11 //获取猫对象 12 Cat cat = (Cat) tool.getObject(); 13 } 14 } 15 16 17 //工具类 18 class Tool { 19 private Object object; 20 21 public Object getObject() { 22 return object; 23 } 24 25 public void setObject(Object object) { 26 this.object = object; 27 } 28 } 29 30 //动物类 31 class Animal { 32 private String name; 33 private String color; 34 35 public Animal() { 36 } 37 38 public Animal(String name, String color) { 39 this.name = name; 40 this.color = color; 41 } 42 43 public String getName() { 44 return name; 45 } 46 47 public void setName(String name) { 48 this.name = name; 49 } 50 51 public String getColor() { 52 return color; 53 } 54 55 public void setColor(String color) { 56 this.color = color; 57 } 58 59 @Override 60 public String toString() { 61 return "Animal{" + 62 "name='" + name + '\'' + 63 ", color='" + color + '\'' + 64 '}'; 65 } 66 } 67 68 //狗类 69 class Dog extends Animal { 70 71 public Dog() { 72 } 73 74 public Dog(String name, String color) { 75 super(name, color); 76 } 77 } 78 79 //猫类 80 class Cat extends Animal { 81 public Cat() { 82 } 83 84 public Cat(String name, String color) { 85 super(name, color); 86 } 87 }
我们来看这段代码,工具类Tool,他是可以设置任意对象的,即Object,那么Cat和Dog都是继承Animal类,当往工具类设置Dog类时,Tool是可以接收的,获取时也可以强转成Cat类时编译也是可以的,但是运行时:
java.lang.ClassCastException类型转换异常,因此在这里如果没使用泛型就会导致在运行时存在类型转换异常,因此会出现安全隐患。
那么,加了泛型之后呢?请看代码:(将Tool加上泛型)
1 //工具类 2 class Tool<T> { 3 private T object; 4 5 public T getObject() { 6 return object; 7 } 8 9 public void setObject(T object) { 10 this.object = object; 11 } 12 }
加上泛型之后,等于约束了Tool能存放的类型,一旦存放的不是该类型,那么就直接在编译期间就提示错误,这也就是为什么泛型将运行期的错误转移到编译期了。
二、泛型方法的使用
1.成员方法的泛型
泛型方法(扑通)也就是把泛型定义在方法上,定义格式:
public <泛型类型> 返回类型 方法名(泛型类型 变量名)
public<T> void move(T t) { //方法类型最好与类方形一致 System.out.println(t); //如果不一致,那么要在方法上声明类型 }
完整版:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class Demo { 2 public static void main(String[] args){ 3 //创建工具类对象 4 Tool<Dog> tool = new Tool<>(); 5 tool.move(new Dog("泰迪","屎黄色")); 6 tool.move(new Cat("旺财","黄色")); 7 } 8 } 9 10 11 //工具类 12 class Tool<T> { 13 private T object; 14 15 public T getObject() { 16 return object; 17 } 18 19 public void setObject(T object) { 20 this.object = object; 21 } 22 23 //成员方法 24 public<T> void move(T t) { //方法类型最好与类方形一致 25 System.out.println(t); //如果不一致,那么要在方法上声明类型 26 } 27 28 } 29 30 //动物类 31 class Animal { 32 private String name; 33 private String color; 34 35 public Animal() { 36 } 37 38 public Animal(String name, String color) { 39 this.name = name; 40 this.color = color; 41 } 42 43 public String getName() { 44 return name; 45 } 46 47 public void setName(String name) { 48 this.name = name; 49 } 50 51 public String getColor() { 52 return color; 53 } 54 55 public void setColor(String color) { 56 this.color = color; 57 } 58 59 @Override 60 public String toString() { 61 return "Animal{" + 62 "name='" + name + '\'' + 63 ", color='" + color + '\'' + 64 '}'; 65 } 66 } 67 68 //狗类 69 class Dog extends Animal { 70 71 public Dog() { 72 } 73 74 public Dog(String name, String color) { 75 super(name, color); 76 } 77 } 78 79 //猫类 80 class Cat extends Animal { 81 public Cat() { 82 } 83 84 public Cat(String name, String color) { 85 super(name, color); 86 } 87 }
结果:
2.静态方法的泛型
定义格式:public static <泛型类型> 返回类型 方法名(泛型类型 变量名)
//静态成员方法泛型 public static<Q> void show(Q q){ //静态方法必须声明自己的泛型 System.out.println(q); }
为什么要声明自己的泛型,这是因为调用move方法是在创建对象以后调用,而静态方法是类加载就可以调用,他们的生命周期不一样。
看代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class Demo { 2 public static void main(String[] args){ 3 //创建工具类对象 4 Tool<Dog> tool = new Tool<>(); 5 tool.move(new Dog("泰迪","屎黄色")); 6 Tool.show(new Cat("旺财","黄色")); 7 } 8 } 9 10 11 //工具类 12 class Tool<T> { 13 private T object; 14 15 public T getObject() { 16 return object; 17 } 18 19 public void setObject(T object) { 20 this.object = object; 21 } 22 23 //成员方法 24 public<T> void move(T t) { //方法类型最好与类方形一致 25 System.out.println(t); //如果不一致,那么要在方法上声明类型 26 } 27 28 //静态成员方法泛型 29 public static<Q> void show(Q q){ //静态方法必须声明自己的泛型 30 System.out.println(q); 31 } 32 33 } 34 35 //动物类 36 class Animal { 37 private String name; 38 private String color; 39 40 public Animal() { 41 } 42 43 public Animal(String name, String color) { 44 this.name = name; 45 this.color = color; 46 } 47 48 public String getName() { 49 return name; 50 } 51 52 public void setName(String name) { 53 this.name = name; 54 } 55 56 public String getColor() { 57 return color; 58 } 59 60 public void setColor(String color) { 61 this.color = color; 62 } 63 64 @Override 65 public String toString() { 66 return "Animal{" + 67 "name='" + name + '\'' + 68 ", color='" + color + '\'' + 69 '}'; 70 } 71 } 72 73 //狗类 74 class Dog extends Animal { 75 76 public Dog() { 77 } 78 79 public Dog(String name, String color) { 80 super(name, color); 81 } 82 } 83 84 //猫类 85 class Cat extends Animal { 86 public Cat() { 87 } 88 89 public Cat(String name, String color) { 90 super(name, color); 91 } 92 }
注意这个:
结果:
当通过类名.方法名时,那么还没有创建对象,不会让你去约束泛型,因此必须在静态方法上加上自己的泛型。
三、泛型接口的概述和使用
1.概述
泛型接口,也就是在接口上定义泛型。
2.定义格式:
public interface 接口名<泛型类型>
如:
//接口泛型 interface Inter<String>{ void method(String str); }
Code:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class Test_Generic { 2 public static void main(String[] args){ 3 Inter inter = new ImplInter(); 4 inter.method("唐豆豆,你个迷人的小妖精"); 5 } 6 } 7 //接口泛型 8 interface Inter<String>{ 9 void method(String str); 10 } 11 //实现接口重写方法 12 class ImplInter implements Inter<String>{ 13 14 @Override 15 public void method(String str) { 16 System.out.println(str); 17 } 18 }
结果:
泛型后面还有一点会再说,将集合复习完毕之时,再补充一点关于泛型的通配符,仅作了解。
如有错误之处,欢迎指正。
邮箱:it_chang@126.com