黑马程序员----泛型

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

 泛型


1、泛型的由来

在泛型没有产生之前,java集合有个缺点:当我们把一个对象存入集合中后,集合就会忘记这个对象的数据类型,当再次读取这个对象的时候,该对象的编译类型就变成了Object(运行时候类型没变)。集合之所以设计成这样,是因为程序员在设计集合的时候,不会知道我们需要他来存贮什么,所以他们只好把集合设计成能保存任何类型的对象,当我们在使用集合元素的时候,只好对它进行数据类型强转。这既增加了编译的难易程度,也可能会引起异常。
所以,在JDK1.5以后,就增加了泛型,起很大程度上就是为了让集合能记住自身的元素类型,并在编译的时候就能检查出集合中元素的类型,如果试图向集合中添加其他的元素类型,编译器就会报错。
增加了泛型可以让集合变得更简单,同时也增强了代码的健壮性,运行的时候也不会产生ClassCastException。

2、使用泛型----简单的使用

对于JDK1.5后,增加了泛型之后,我们在定义集合的方式
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class fanxin {
    public static void main(String[] args) {
        //创建带有泛型的集合,集合里面存入Integer类型的元素
        List<Integer>  list=new ArrayList<Integer>();
        //向集合中添加符合泛型的元素
        list.add(12);
        list.add(1);
        list.add(13);
        list.add(8);
        list.add(19);
        //用迭代器遍历集合,取出其中的元素
        Iterator<Integer> it=list.iterator();
        while(it.hasNext())
        {
            Integer str=it.next();
            System.out.println(str);//打印取出的元素
        }
    }

}


上面程序成功创建了一个集合:带有集合只能存贮Integer类型的元素的集合,不能够存贮其他的元素类型。由上式很容易的就看出,创建泛型集合的方式就是在集合的后面用一对尖括号括住元素类型并跟在集合的后面。,
上面的代码不仅更加健壮,程序再也不能像集合中添加任意数据类型的元素了,从而在以后的遍历中不需要进行类型的强制转换。

3、深入泛型

所谓泛型:就是允许在定义接口、类时候指定类型参数,这个类型将在申明变量、创建对象的时候确定。

3.1  定义泛型接口、泛型类

public class Apple <T>{
    private T t;
    public Apple(){}
    public Apple(T t)
    {
        this.t=t;
    }
    public T getT() {
        return t;
    }
    public void setT(T t) {
        this.t = t;
    }
}


以上就是一个简单的泛型类,值得注意的是:在定义泛型类的构造函数的时候,不需要将泛型也传递进来,可以使用泛型形参来定义方法。在实际的创建对象的时候,再传入我们需要的泛型类型。
在继承带有泛型的类的时候,我们必须明确指出泛型的类型或者不继承泛型:class A extends Apple<String>{}或者class A extends Apple{}这就是正确的写法

3.2  泛型在内存中的验证

import java.util.ArrayList;
import java.util.List;
public class Apple {
    public static void main(String[] args)
    {
        List<Integer> list=new ArrayList<Integer>();
        List<String> list1=new ArrayList<String>();
        Class clazz=list.getClass();
        Class clazz1=list1.getClass();
        System.out.println(clazz==clazz1);
        
    }
}


上述结果是true,及说明泛型并不随着类的加载而加载,在通过虚拟机编译之后,集合上定义的泛型就会消失。

3.3  泛型的界定----?通配符的使用

当我们不知道集合中要存入什么元素的时候,就可以使用?通配符
List<? super Integer > list3=new ArrayList<Number>();//这就表示限定上限
List<? extends Number > list4=new ArrayList<Number>();//这就表示限定下限

3.4  泛型方法的使用

前面介绍了泛型在接口、类上的使用,在实际的编程过程中,我们还会遇到哪些不需要在类上定义泛型,只需要在方法上定义泛型的时候。
所谓的泛型方法就是:在定义方法的时候加上一个或者多个类型形参,类型形参定在返回值的前面。
<T>void  getT(T[] t,Collection<T>  c)
    {
        for(T a:t)
        {
            c.add(a);
        }
    }


这个例子的意思就是:将数组中T类型的元素,只能添加到泛型为T的集合c中。

3.5 使用反射来获取泛型信息----获取集合的泛型类型

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.ParameterMetaData;
import java.util.HashMap;
import java.util.Map;
public class GenericParameterizedType {

    private Map<Integer,String> map;
    public static void main(String[] args)throws Exception {
        
        Class clazz=GenericParameterizedType.class;
        Field field=clazz.getDeclaredField("map");
        //System.out.println(field);
        Class f=field.getType();//返回的是field所对应的元素声明的类型,不带泛型
        System.out.println(f);//返回结果就是java.util.Map
        Type ftype=field.getGenericType();//带有泛型的变量名称
        System.out.println(ftype);//打印结果就是Map<Integer,String>
        if(ftype instanceof ParameterizedType)
        {
            ParameterizedType  pty=(ParameterizedType)ftype;
            Type t=pty.getRawType();//得到原始类型
            System.out.println(t);//Map
            Type[] types=pty.getActualTypeArguments();//返回实际参数类型数组
            for(Type tt:types)
            {
                System.out.println(tt);//Integer  String
            }
        }
    }
}


3.6 泛型在集合中的典型运用

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
public class MapTest {
    public static void main(String[] args) {
        Map<String ,Integer> map=new HashMap<String,Integer>();
        map.put("lisi", 20);
        map.put("zhansan", 21);
        map.put("wangwu", 24);
        map.put("zhouqi", 19);
        Set<Map.Entry<String,Integer>>  ss=map.entrySet();
        Iterator<Map.Entry<String,Integer>> it=ss.iterator();
        while(it.hasNext())
        {
            Map.Entry<String,Integer> mp=it.next();
            String str=mp.getKey();
            System.out.println(str);
            Integer x=mp.getValue();
            System.out.println(x);
        }
    }
}


4、总结

泛型的出现,减少了在编程过程中错误的出现几率,同时增强了代码的健壮性。同时泛型参数以及泛型方法的出现,更是提高了编程的简单、简洁。


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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值