Java泛型集合
所谓泛型就是允许在定义类、接口时指定类型形参,这个类型形参将在声明变量、创建对象时确定。增加了泛型支持后的集合,完全可以记住集合
中元素的类型,并可以在编译时检查集合中元素的类型。即解决一些安全问题,同时还可以让代码变得更加简洁。
一、使用泛型
泛型的格式:通过<>来定义要操作的引用数据类型
创建一个只存放字符串的对象,代码如下:
package com.csu.test1; import java.util.ArrayList; import java.util.List; public class GenericDemo { public static void main(String[] args) { //创建一个只能保存字符串的ArrayList集合 List<String> strList=new ArrayList<String>(); //如果存放其他类型的对象时会出现编译错误 strList.add("chaofn"); System.out.println(strList); } }
使用泛型的好处:
1、将运行时期出现的ClassCastExcpetion , 转移到了编译时期。方便于程序员解决问题,让运行时期问题减少。
2、避免了强制转换的麻烦。
如下代码可以解释这一点:
package com.csu.test1; import java.util.ArrayList; import java.util.Iterator; import java.util.List; class StringDemo { String name; public StringDemo(String name){ this.name=name; } } public class GenericDemo { public static void main(String[] args) { //创建一个只能保存字符串的ArrayList集合 List ls=new ArrayList(); //如果存放其他类型的对象时会出现编译错误 ls.add(new StringDemo("chaofn01")); ls.add(new StringDemo("chaofn02")); ls.add(new StringDemo("chaofn03")); ls.add(new StringDemo("chaofn04")); ls.add(1000); MyIterator(ls); } public static void MyIterator(List ls){ Iterator it=ls.iterator(); while(it.hasNext()){ StringDemo s=(StringDemo) it.next(); System.out.println(s.name); } } }
运行结果:
chaofn01 chaofn02 Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to com.csu.test1.StringDemo at com.csu.test1.GenericDemo.MyIterator(GenericDemo.java:34) at com.csu.test1.GenericDemo.main(GenericDemo.java:27) chaofn03 chaofn04
在调用MyIterator(List ls) 方法时会发生ClassCastException 异常。而且在编译时是不会有任何提示,只有运行时会出现,所以使的程序存在安全隐患。
如果使用泛型则会在编译时提示错误,而且在遍历时不需要强制转换。如:
import java.util.ArrayList; import java.util.Iterator; import java.util.List; class StringDemo { String name; public StringDemo(String name){ this.name=name; } } public class GenericDemo { public static void main(String[] args) { //创建一个只能保存字符串的ArrayList集合 List<StringDemo> ls=new ArrayList<StringDemo>(); //如果存放其他类型的对象时会出现编译错误 ls.add(new StringDemo("chaofn01")); ls.add(new StringDemo("chaofn02")); ls.add(new StringDemo("chaofn03")); ls.add(new StringDemo("chaofn04")); //下面一行代码在编译时会出错 //ls.add(1000); MyIterator(ls); } public static void MyIterator(List<StringDemo> ls){ Iterator<StringDemo> it=ls.iterator(); while(it.hasNext()){ //不需要强制转化成StringDemo StringDemo s= it.next(); System.out.println(s.name); } } }
二、自定义泛型类:
除了Java提供了一些类增加了泛型支持外,我们可以自定义泛型支持类。
那么在什么时候定义泛型类呢?
当类中操作的引用数据类型不确定时可以定义泛型类。
格式如下:
class Tools<T> { }
例如:定义一个Tools 类 用来完成打印操作,但是应为不知道要操作的数据类型是什么,所以可以定义成泛型类。具体操作:
//定义一个工具类Tools 2 //因为不知道要操作的类型是什么所以增加泛型支持 3 class Tools<T> 4 { 5 // 包含输出函数: 6 public void sop(T t) 7 { 8 System.out.println("sop:"+t); 9 } 10 } 11 //定义一个Books 类 12 class Books 13 { 14 private String name ; 15 public Books(String name) 16 { 17 this.name = name ; 18 } 19 // 重写toString 方法 20 public String toString() 21 { 22 return "name = " + name ; 23 } 24 } 25 public class GenericText 26 { 27 public static void main(String[] args) 28 { 29 // 创建一个Tools 实例tool ,定义 tool 要操作的数据类型为Books 30 Tools<Books> tool = new Tools<Books>() ; 31 // tool 可以操作 Books 类型,还可以操作Integer 类型和String类型。 32 tool.sop(new Books("神雕侠侣")); 33 } }
泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类型,
而且类型还不确定,那么可以将泛型定义在方法上。
三、自定义泛型方法
定义泛型方法格式如下:
public <T> void show(T t) 注意:<>放在修饰符后面,返回值前面 { }
//定义一个工具类Tools 2 //因为不知道要操作的类型是什么所增加泛型支持 3 class Tools<T> 4 { 5 // 包含输出函数: 6 public void sop(T t) 7 { 8 System.out.println("sop:"+t); 9 } 10 // 定义的泛型方法: 11 public <T> void show (T t) 12 { 13 System.out.println("show:"+t); 14 } 15 } 16 //定义一个Books 类 17 class Books 18 { 19 private String name ; 20 public Books(String name) 21 { 22 this.name = name ; 23 } 24 // 重写toString 方法 25 public String toString() 26 { 27 return "name = " + name ; 28 } 29 } 30 public class GenericText 31 { 32 public static void main(String[] args) 33 { 34 // 创建一个Tools 实例tool ,定义 tool 要操作的数据类型为Books 35 Tools<Books> tool = new Tools<Books>() ; 36 // tool 可以操作 Books 类型,还可以操作Integer 类型和String类型。 37 tool.sop(new Books("神雕侠侣")); 38 tool.show(new Books("神雕侠侣")) ; 39 // 下面的方法编译时会报错》、: 40 tool.sop(1000) ; 41 tool.sop("String") ; 42 43 // 但下面却不会报错,并且正常运行。 44 tool.show(1000) ; 45 tool.show("String") ; 46 } 47 }