泛型的使用

来源:互联网 发布:支持json编辑 编辑:程序博客网 时间:2024/05/18 02:28
/*泛型入门*/
java集合有个缺点把一个对像放进集合之后集合就会忘记这个对像的数据类型
当再次取出该对象时候,该对象的编译类型就变成了Object类型java集合之所
以被设计成这样就是因为集合的设计者不知道我们会用集合保存什么类型的对像
所以把集合设计成能保存任何类型的对象只要求具有很好的通用性。
这样做带来如下两个问题:
1:集合对元素的类型没有限制这可能会依法异常
2:由于把对象放进去的时候没有考虑类型但是取出来的时候是Object类型那么问题来了
如果想要转换成放进去之前的元素类型那么就要进行强制类型转换增加了编程的复杂度
而且还可能引发ClassCaxtException。
下面介绍编译的时候不检查类型可能引发的异常:
public class ListErr 
{
public static void main(String[] args) 
{
//创建一个只想保留字符串的List结婚
List strList = new ArrayList();
strList.add("疯狂java讲义");
strList.add("疯狂android讲义");
//一不小心将Integer对像放进了集合中
atrList.add(5);
//下面的语句将会出现错误
strList.forEach(str->System.out.println(((String)str).length()));

}
}
使用泛型
从java5以后,java引入了"参数化类型"的概念,允许程序在创建集合时指定结合元素的类型,参数化类型被称作泛型。
使用泛型修改之前的程序:


public class ListErr 
{
public static void main(String[] args) 
{
//创建一个只想保留字符串的List结婚
List<String> strList = new ArrayList<String>();
strList.add("疯狂java讲义");
strList.add("疯狂android讲义");
//一不小心将Integer对像放进了集合中
//这样的话这个就会在编译的时候出现错误!
atrList.add(5);
//本句话中将不会出现错误而且不需要进行强制类型转换
strList.forEach(str->System.out.println(str.length()));

}
}
在集合接口、类后增加尖括号尖括号中增加数据类型表名它只能保存特定类型的对像上面的代码不仅更加健壮而且程序
更加的简洁集合自动记住所有元素的数据类型无需对集合元素进行强制类型转换。


java 7 反省的“菱形”语法


java7以前,如果使用了带泛型的接口,类定义变量,那么吊哟偶个构造器创建对像构造器的后面也必须带泛型,这显得有些多余了
例如:List<String> StrList = new ArrayList<String>();
上面语句是多余的但是在java7之前是必须要写的但是经过jjava7的改进之后只需要使用菱形语法这样的话就能大大缩短时间
java可以自动的判断类型例如:
例如:List<String> StrList = new ArrayList<>();只需要写上<>不再需要写上完整的类型就行了
//需要注意的是java斑病应该在1.8才能编译下面的程序!
import java.util.*;


public class DiamondTest
{
public static void main(String[] args)
{
// Java自动推断出ArrayList的<>里应该是String
List<String> books = new ArrayList<>();
books.add("我是李刚");
books.add("我不是李刚");
// 遍历books集合,集合元素就是String类型
books.forEach(ele -> System.out.println(ele.length()));
// Java自动推断出HashMap的<>里应该是String , List<String>
Map<String , List<String>> schoolsInfo = new HashMap<>();
// Java自动推断出ArrayList的<>里应该是String
List<String> schools = new ArrayList<>();
schools.add("斜月三星洞");
schools.add("西天取经路");
schoolsInfo.put("孙悟空" , schools);
// 遍历Map时,Map的key是String类型,value是List<String>类型
schoolsInfo.forEach((key , value) -> System.out.println(key + "-->" + value));
}
}


深入泛型


   所谓泛型就是定义类、接口、方法时使用类型形参,这个类型形参将在声明变量、创建对像、调用方法时动态的指定
泛型允许在定义接口、类时声明类型形参除此之外我们见到的Iterator<E> Map<E> 这表明它们是一种特殊形式的数据
类型是一种和set不同的数据类型可以认为是其子类


需要注意的是:
   包含泛型声明的类型可以在定义变量、创建兑现时传入一个类型实参,从而可以动态地生成无数朵花和逻辑上的子类,
但是这种子类在物理上是不存在的
创建出于自己的带反省声明的类




// 定义Apple类时使用了泛型声明
public class Apple<T>
{
// 使用T类型形参定义实例变量
private T info;
public Apple(){}
// 下面方法中使用T类型形参来定义构造器
public Apple(T info)
{
this.info = info;
}
public void setInfo(T info)
{
this.info = info;
}
public T getInfo()
{
return this.info;
}
public static void main(String[] args)
{
// 由于传给T形参的是String,所以构造器参数只能是String
Apple<String> a1 = new Apple<>("苹果");
System.out.println(a1.getInfo());
// 由于传给T形参的是Double,所以构造器参数只能是Double或double
Apple<Double> a2 = new Apple<>(5.67);
System.out.println(a2.getInfo());
}
}
这样我们在使用Apple<T>时候就可以为形参传入实际类型需要注意的是为类定义构造器
的时候构造器的名称还是类名不要增加反省声明例如Apple<T>的构造器就是Apple不是Apple<T>
此外还可以派生子类、定义泛型方法、使用通配符、泛型和泛型数组、通配符的上限和下限如果
想深入学习的话请自行查阅
0 0