首页 > 技术文章 > 泛型

xiaomu0 2019-05-02 01:19 原文

                                   泛型

泛型是Java1.5之后添加的,它可以帮我们建立类型安全的集合。

泛型的本质就是“数据类型的参数化”,我们可以吧泛型理解为数据类型的一个占位符(形式参数),即告诉编译器,在调用泛型时必须传入实际类型。

集合可以存储任何类型的对象,但是,当把一个对象存入集合后,集合会忘记这个对象的类型,将给对象从集合中取出时,这个对象的编译类型就变成了Object的类型,换句话说,在程序中无法确定一个集合中的元素到底是什么类型的,那么在取出元素时,如果进行强制类型转换,就很容易出错

import java.util.*;
public class Exceptle{
    public static void main(String[] args){
        ArrayList list = new ArrayList();   // 创建ArrayList集合
        list.add("String");     // 添加字符串对象
        list.add("Colllection");    
        list.add(1);      // 添加Integer对象
        for(Object object:list){   // 遍历集合
            String str = (String) object;   // 强制转换为String类型
        }
    }
}

像List集合中存入了3个元素,分别是两个字符串和一个整数,在取出这些元素时,都将他们强转为String类型,由于Integer对象无法转化为String类型,因此在程序运行时出现错误,为解决这个问题,在java中引入了“参数化类型”这个概念,他可以限定方法操作的数据类型,在定义集合类时,使用“参数化类型”的方式,指定该类中方法操作的数据类型

具体格式:

ArrayList<参数化类型> list = new ArrayList<参数化类型>();

 

可以将第四行代码改为:

ArrayList<String> list = new ArrayList<String>();         // 创建集合对象并指定泛型对象为String类型

 

上面例子报错就是因为修改后的代码限定了几何元素的数据类型,ArrayList<String>这样的集合类型只能存储String 类型的元素,程序在编译时,编译器检查出Integer类型的元素与List集合的规定的类型不匹配,所以报错。

 

import java.util.*;
public class Exceptle{
    public static void main(String[] args){
        ArrayList<String> list = new ArrayList<String>();    // 创建ArrayList集合
        list.add("String");     // 添加字符串对象
        list.add("Colllection");    
        list.add(1);      // 添加Integer对象
        for(Object object:list){   // 遍历集合
            String str = (String) object;   // 强制转换为String类型
        }
    }
}

适用泛型规定了ArrarList集合只能存储String类型元素,之后向集合中存入了两个String类型的元素,并对这个集合进行遍历。

注:再使用泛型后遍历集合元素时,可以指定集合元素类型为String,而不是Object,这样就避免了在程序中进行强制类型转换。

定义泛型:

void save(参数类型 参数){…………}
返回值 参数类型 get(){………………}

 

save()方法参数类型需要定义为Object类型,同样get()方法的返回值也需要是Object类型,但是当使用get()方法取出这个值时,有可能忘记当初存储的是什么类型的值,在取出时将其转换为String类型。

class CachePool{
    Object temp;
    public void save(Object temp){
        this.temp = temp;
    }
    public Object get(){
        return temp;
    }
}
public class Excemple{
    public static void main(String[] args){
        CachePool pool = new CachePool();
        pool.save(new Integer(1));
        String temp = pool.get();
        System.out.println(temp);
    }
}

 

编译会报错,在13行位置存入了一个Ineger类型数据,在14行取出这个数据时,将数据转换成了String,出现了数据类型不匹配的问题,为了避免这个问题就可以使用泛型。如果在自定义一个类CachePool时使用<T>声明参数类型(T就是Type的缩写,也可以使用其他字符,为了方便理解都定义为T),将save()方法的参数类型和get()方法的参数类型都声明为T,那么在存入元素时,元素就被限制了,容器中就只能存储T类型的元素,在取出元素时就无需再进行转换了。

如:

class CachePool<T>{    // 创建类时,声明参数类型为T
    T temp;
    public void save(T temp){
        this.temp = temp;
    }
    public T get(){
        return temp;
    }
}
public class Excemple{
    public static void main(String[] args){
        // 实例化对象时,传入参数为Integer类型
        CachePool<Integer> pool = new CachePool<Integer>();
        pool.save(new Integer(1));
        Integer temp = pool.get();
        System.out.println(temp);
    }
}

 

在定义CachePool类时,声明了参数类型为T,在实例化对象时通过<Integer>将参数T指定为Integer类型,同时在调用save()方法传入的数据也是Integer类型,调用get()方法取出元素时也是Integer类型,不用再进行类型转换。

 

 

推荐阅读