泛型
泛型是提供给javac编译器使用的,可以限定集合中输入类型,让编译器挡住源程序中的非法输入。
好处:1.将运行时的类型转换问题转换成编译失败,让问题体现在编译时期以便处理
2.避免强制转型的麻烦。
在JDK1.5中,还可以按原来的方式将不同类型的数据装到一个集合中,但编译器会报告unchecked错误。
需要注意的是:编译器在编辑带类型说明的集合时会去除掉“类型”信息,所以getClass()方法返回的值和原始类型一模一样。
泛型写法:一般在集合中后面加上<>,中间写入参数类型。
例:ArrayList<E>和ArrayList<Integer>:
整个称为ArrayList<E>类型
E称为类型变量或类型参数
整个ArrayList<Integer>称为参数化的类型
Integer称为类型参数的实例或实际类型参数
<>念做typeof
ArrayList原始类型
注意:
参数化类型不考虑类型参数的继承关系
Vector<String> v=new Vector<Object>();这是错误的
在创建数组实例时数组元素不可使用参数化类型:
Vector<Integer> vector ist[] =new Vector<Integer>[10];这是错误的
泛型的?通配符:
?表示可以接受任意参数换类型。
例如定义一个方法可以打印出任意参数化类型的集合,这个方法如何定义呢?
1.public static void printCollection(Collection<object> cols)
{cols=new HashSet<Date>},这种就是错误的,这个方法中的object知识说明接受的参数是object,是一种具体类型
2.public static void printCollection(Collection<?> cols)
{
cols.add("String")>>错误的,因为不知道未来匹配的一定是String
cols.size(),没错此方法与参数类型没有联系。
}
所以需要注意的是:带统通配符方法与类型有关的方法不可以调用。
通配符的上限和下限:
上限:?extends E:可以接收E类型或者E的子类型对象。
下限:?super E:可以接收E类型或者E的父类型对象。
自定义泛型类:
package xiaobing.collection;
/*
* 什么时候定义泛型类
*当类中要操作的引用数据类型不确定的时候
*早起用Object类来扩展
*有泛型后可以用泛型来完成扩展
*/
/*
* 下面的需求时,定义工具类来进行类的初始化
* 定义工具类来进行工人和学生的工具类
*/
//定义工人类
class Worker
{
}
//定义学生类
class Student
{
}
//泛型前做法
/*
class Tool
{
private Object obj;
public void setObject(Object obj)
{
this.obj=obj;
}
public Object getObject()
{
return obj;
}
}*/
//定义泛型类
class Utils<QQ>
{
private QQ q;
public void getObject(QQ q)
{
this.q=q;
}
public QQ getObject()
{
return q;
}
}
public class GenericDemo1 {
public static void main(String[] args)
{
Utils<Worker> u=new Utils<Worker>();
u.getObject(new Worker());
//u.getObject(new Student())编译直接无法通过,将问题直接反应在编译时期
//泛型前调用
/*
Tool t=new Tool();
t.getObject(new Student());
Worker w=(Worker) t.getObject(); 错误出现类型转换异常,但编译是可以通过的
运行出现异常,只能重新调用,所以比较麻烦
*/
//
}
}
自定义泛型方法:
package xiaobing.collection;
/*
* 泛型类定义的泛型在整个类中有效,如果被方法使用
* 那么泛型类的对象明确指定的具体类型后所要操作的类型就已经固定了,
* 这样就存在了一定的局限性
*
* 为了让不同的方法可以操作不同的类型,而且类型还不确定
* 可以将泛型定义在方法上
*/
/*
* 定义泛型方法使其可以执行不同类型数据
*/
/*
* 特别需要注意:
* 静态方法不可以访问类上定义的泛型,如果静态方法操作的引用数据类型不确定可以将
* 泛型定义到方法上。public static<T> void 放在返回值的前面
*/
class Demo<T>//T一确定,操作的类型就确定
{
public void show(T t)
{
System.out.println("show+"+t);
}
public void print(T t)
{
System.out.println("print:"+t);
}
}
//将泛型定义到方法上
class Demo01
{
public <T> void show(T t)
{
System.out.println("show+"+t);
}
public<Q> void print(Q q)
{
System.out.println("print:"+q);
}
}
public class GeneriDemo01 {
public static void main(String[] args)
{
//使方法可以操作int数据
Demo<Integer> d=new Demo<Integer>();
d.show(new Integer(4));
d.print(9);
//使方法可以操作int数据
Demo<String> d1=new Demo<String>();
d1.show("hah");
d1.print("sasf");
//调用Demo01
Demo01 d2=new Demo01();
d2.show("hha");
d.print(2);
}
}