——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
为什么定义泛型?
定义了一个List类型的集合,先向其中加入了两个字符串类型的值,随后加入一个Integer类型的值。这是完全允许的,因为此时list默认的类型为Object类型。在之后的循环中取出元素值时,由于是Object的类型,所以取出后要求做强制类型转换,把Object转换为字符串或者Integer类型,在转换过程中,可能会出现转换的类型不符,可能把字符串转为为Integer类型,运行时程序会报错。为了避免强制类型转换以及在类型转换中出错,就引入了泛型,避免了强制类型转换,把出现的错误放在了编译期解决。
泛型
所谓泛型是指将类型参数化,在使用集合时指定集合存放的数据类型,在编译期就能过对存放的类型进行限定,因为指定了存放数据的类型,在取数据时不需要强制类型转换,对于数据与引用数据类型出现的不符也能够在编译期被检测出来,不用等到运行期出现错误。这种参数类型可以用在类、接口和方法的创建中。
泛型的定义:
ArrayList 泛型类型集合
ArrayListT类型变量或说类型参数
ArrayList 中的Integer为类型的实例或实际类型参数
没用泛型:
/**
* 不用泛型的集合
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList list = new ArrayList();
list.add("abc");
list.add(12);
String str = (String)list.get(0);
Integer i = (Integer)list.get(1);
}
}
泛型的应用
/**
* 泛型集合
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<String> list = new ArrayList<String>();
list.add("abc");
list.add("OK");
String str1 = list.get(0);
String str2 = list.get(1);
}
}
泛型是提供给javac编译器使用的可以限定集合中的的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去掉“类型”信息,使的程序中的非法输入,使的程序运行效率不受影响,对于参数化的泛型类型,getClass()类型的的返回值和原类型数据完全一样。由于编译生成的字节码会去掉泛型的类型信息,只有跳过编译器,就可以向泛型集合汇中加进其他类型的数据。
泛型练习:
/**
* 判断泛型集合与非泛型集合是否相同
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//有泛型的集合
ArrayList<String> list1 = new ArrayList<String>();
//没有泛型的集合
ArrayList list2 = new ArrayList();
//判断是否是同一字节码
System.out.println(list1.getClass()==list2.getClass());
}
运行的结果是true,字节码相同。
/**
* 利用反射对泛型集合加进其他数据类型
*/
public static void main(String[] args) {
//定义泛型
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(15);
try {
//获得add的方法,加进String类型
Class cla = list.getClass();
Method method = cla.getMethod("add", Object.class);
method.invoke(list, "abc");
} catch ( Exception e) {
e.printStackTrace();
}
System.out.println(list.get(1));
}
}
运行能够打印出字符串数据,说明字符已经加进去。
泛型不存在继承关系
错:
ArrayList list = new ArrayList();
错:
ArrayList = new ArrayList();
泛型与原始数据兼容:
ArrayList list = new ArrayList();
ArrayList = new ArrayList();
通配符:
只能调用调用不涉及类型参数的的函数
限定通配符的上边界(指定类型的范围):
ArrayList<? Extends Number> x = new`ArrayList<Integer>();
ArrayList<? Extends Number> x = new ArrayList<String>();
限定通配符的下边界:
正确:
ArrayList<?super Integer> x =new ArrayList<Numder>();
错误:
AttayList<?super Integer> x=new ArrayList<Byte>();
练习:
/**
* 泛型练习,HashMap的应用
*/
public static void main(String[] args) {
//定义泛型HashMap
Map<String,Integer> map = new HashMap<String, Integer>();
map.put("张三",14);
map.put("李四", 16);
map.put("王五", 18);
//取值
Set<Map.Entry<String,Integer>> set = map.entrySet();
for(Map.Entry<String, Integer> entry:set)
{
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
}
泛型方法的定义
/*泛型的方法的定义
* <T>指定T为泛型
* 方法中的所有的T为同一类型数据
*/
public <T> T way(T x,T y)
{
System.out.println(x+":"+y);
return null;
}
练习:
public static void main(String[] args) {
Integer i = way(12,13);
//当方法中出现不同数据类型时,去类型的共同父类
Number number = way(12.5,12);
Object abj = way("abc",11);
}
/*泛型的方法的定义
* <T>指定T为泛型
* 方法中的所有的T为同一类型数据
*/
static public <T> T way(T x,T y)
{
System.out.println(x+":"+y);
return null;
}
可以对泛型进行范围的限定:
//限定泛型范围
public <T extends Number> T way(T x,T y)
{
System.out.println(x+":"+y);
return null;
}