黑马程序员----泛型(Generic)

来源:互联网 发布:软件操作手册 编辑:程序博客网 时间:2024/06/05 17:35

——- android培训、java培训、期待与您交流! ———-


泛型(Generic)

泛型:jdk1.5版本以后出现的新特性,用以解决安全问题,是一个类型安全机制。

在定义集合的时候,也能像数字一样明确里面装的是什么类型的对象;
好处:
1.将运行时期出现的问题转移到了编译时期,方便于程序员解决问题,让运行时期的问题减少;
2.避免了强制转换的麻烦;

泛型的格式:通过<>来定义要操作的引用数据类型;

在使用java提供的对象时,什么时候使用泛型呢?
通常情况下,在集合框架中很常见,只要按见到<>,就要定义泛型。

其实<>就是用来接收类型的
当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可,如同函数传参数;

public class Generic_0 {public static void main(String[] args){/*//泛型可以借鉴数组来完成:int[]arr=new int[3];arr[0]=4;//arr[1]=3.5;//损失精度,编译时就会报错;*///泛型:ArrayList<String> al=new ArrayList<String>();//在尖括号里面规定类型,这里的类型可以变化;//小引例//ArrayList al=new ArrayList();al.add("abc001");al.add("abc00002");al.add("abc003000");al.add("abc0004");//al.add(new Integer(4));//集合中可以添加对象,但是不能添加基本的数据类型,但是在1.5版本之后可以添加基本数据类型,因为基本数据类型有自动拆箱装箱的动作;//al.add(4);//出现运行异常:ClassCastException,类型转换异常;通过泛型将错误转移到编译时期,方便程序员解决;//Iterator it=al.iterator();Iterator<String> it=al.iterator();while(it.hasNext()){//String s=(String)it.next();//强转;String s=it.next();//迭代器中装的也是String,在这里不用强转;System.out.println(s+":"+s.length());//打印元素长度;//类型定义完以后,原来的注意没有了,因为安全了;}}}
注意,在复写HashSet的equals方法时不能使用泛型,因为Object没有泛型,不需要对多对象的类型进行强转,转换之前还要判断是不是基本类型;

什么时候定义泛型?
当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展,现在用泛型来扩展。

泛型可以定义在类上,也可以定义在方法上,泛型定义在方法上,要放在返回值类型的前面,修饰符的后面。
泛型的局限性:
只要对象以确定,要操作的数据类型也就固定了。

泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型也就固定了。

如果要用show打印Integer,show打印String,要怎么做?
为了让不同的方法可以操作不同的类型,而且类型还不确定,那么可以将泛型定义在方法上。

如果要明确一种具体的类型,并且类中的方法都跟着走,就在类上定义泛型;集合就是。

特殊之处:静态方法不可以访问类上定义的泛型,如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上。

//在类上定义泛型:class Demo<T>{public void show(T t){System.out.println("show:"+t);}public void print(T t){System.out.println("print:"+t);}}//在函数上定义泛型:class Demo1{public <T> void show(T t)//将泛型定义在方法上:<T>;{System.out.println("show:"+t);}public <T> void print(T t)//两个T没有关系;{System.out.println("print:"+t);}}//既有泛型类,又有泛型方法:class Demo2<T>{public  void show(T t){System.out.println("show:"+t);}public <Q> void print(Q t){System.out.println("print:"+t);}//特殊:静态方法如何定义泛型?/*public static void method(T t)//T在建立对象的时候才会被明确,T是非静态的类型,不能在非静态的T上定义静态的引用;{System.out.println("method:"+t);}*///解决办法:可以将泛型定义在静态方法上,要将<T>放在static后面。public static <T> void method(T t){System.out.println("method:"+t);}}//泛型定义在接口上:第一,在定义类的时候知道具体的类型;第二,在定义类的时候也不知道具体的类型interface Inter<T>{void show(T t);}//知道具体的类型class Demo3_1 implements Inter<String>//类随着接口走;{@Overridepublic void show(String t) {System.out.println("show_Inter:"+t);}}//不知道具体的类型:class Demo3_2<T> implements Inter<T>//类随着接口走;{@Overridepublic void show(T t) {System.out.println("show_Inter:"+t);}}public class Generic_3 {public static void main(String[] args){//将泛型定义在类上:Demo<String> d=new Demo<String>();d.show("haha");d.print("hehe");Demo<Integer> d1=new Demo<Integer>();d1.show(new Integer(4));//自动装箱;d1.print(9);System.out.println("--------------------------------");//将泛型定义在方法上:Demo1 d0=new Demo1();d0.show("haha");d0.show(new Integer(4));d0.print("123456");d0.print(new Integer(123456));System.out.println("--------------------------------");//既有泛型类又有泛型方法:Demo2<String> d2=new Demo2<String>();d2.show("String");//show只能传入String类型的值;d2.print("String");d2.print(new Integer(5));//不冲突;d2.method("000000");d2.method(5);System.out.println("--------------------------------");//将泛型定义在接口上:Demo3_1 d3=new Demo3_1();d3.show("String");Demo3_2<Integer> d4=new Demo3_2<Integer>();d4.show(4);}}
泛型的限定:
当对象不确定的时候,用一个通配符来表示;

泛型限定包括两种:
1.上限:
    ? extends E:可以接收E类型和E的子类型;
2.下限:
    ? super E:可以接收E类型或者E的父类;

?表示通配符,也可以理解为占位符。

public static void print(ArrayList<?> al){Iterator<?> it=al.iterator();while(it.hasNext()){System.out.println(it.next());System.out.println(((String) it.next()).length());//不能直接打印长度;}}

0 0