泛型

来源:互联网 发布:大数据的结果展现方式 编辑:程序博客网 时间:2024/06/15 13:01

一、为什么要引入泛型?以及泛型的本质?
(1)所谓的要引入泛型,就是创造容器类,这个容器类就是放入要使用对象的地方,而且这个容器比较灵活,可以放任意类型的对象,所以使用泛型的主要目的之一就是指定容器中持有什么类型的对象,而且编译器来保证类型的正确性。
(2)知道了为什么要引入泛型,我们就来认识一下泛型的本质:实质就是参数化类型,也就是说将数据类型作为参数,在使用的时候再指定具体数据类型。
(3)引入泛型的好处:第一可以检查检查数据类型,第二获取数据时自动进行强制类型转换。(其过程只发生在编译阶段);


重点内容介绍完为什么引入泛型,一个很重要的问题就是泛型类型的擦除?
(1)所谓的JAVA泛型擦除就是就是把所有的泛型擦除成原始的object类型;但是如果指定上界的话,就擦除到这个上界;
例如:

Class c1=new ArrayList<String>().getClass();Class c2=new ArrayList<Integer>().getClass();System.out.println(c1==c1);  结果返回的是true;因为它们都是相同的类型object;根据这一信息,我们可以看到java泛型是使用擦除来实现的,这意味着当你在使用泛型时,类型信息就被擦除掉了,你唯一知道的就是你在使用一个对象。

(2)有时我们需要根据情况需要,不想擦除到原始类型,因此就需要规定上界,擦除到这个指定的边界,用extends关键词来指定。
例如:

class GenericFun<T extends Comparable<T>>{}这里讲上界指定到Comparable,即在编译时擦除到Comparable

二、泛型的应用
(1)泛型类
eg: Class Array{ };
注意: T中不可以是简单类型;在使用的时候需指定类型参数;

class GenericMath<T extends Number>{    public int sumFunc(T[] array){        int sum = 0;        for(T val : array){            sum += val.intValue();        }        return sum;    }

(2)泛型方法
eg: public void ( T[] arrray){
}
注意:泛型方法是在参数列表中返回值前面加泛型参数列表;

泛型方法举例1public static <E extends Number> int sumFunc2(E[] array){        int sum = 0;        for(E val : array){            sum += val.intValue();        }        return sum;    }泛型方法举例2//利用Comparable接口创建自己的类进行比较,即实现compareTo方法,    public static <E extends Comparable<E>> E min(E[] array){        E minval=array[0];        for(int i=0;i<array.length;i++){            if(minval.compareTo(array[i])>0){                minval=array[i];                }        }        return minval;    }泛型方法举例3:实现一个静态方法,比较任意类型两个元素的大小,返回boolean    //Integer/Integer     Double/Double      Short/Short    public static <E extends Comparable<E>> boolean compare(E a, E b){        return a.compareTo(b) > 0 ? true : false;    }}

(3)泛型接口

eg: Comparable<Person>;class Person implements Comparable<Person>{    private String name;    private int age;    private String sex;    public Person(String name, int age, String sex) {        super();        this.name = name;        this.age = age;        this.sex = sex;    }    public int age(){        return age;    }    //按姓名进行比较    @Override    public int compareTo(Person o) {        // TODO Auto-generated method stub        return name.compareTo(o.name);    }}//Student继承personclass Student extends Person{    private double score;    public Student(String name, int age, String sex, double score){        super(name, age, sex);        this.score = score;    }}class GenericFunctional{    //比较对象的大小                                   Comparable<Student>没有接口,但是继承了基类Comparable<Person>实现了接口                           // compareTo(?   obj)    public static <E extends Comparable<? super E>> boolean compareObject(E a, E b){        return a.compareTo(b) > 0 ? true : false;    }    //main函数中添加代码,定义两个student对象和一个比较器对象,进行学生之间的自定义比较    public static <E> boolean compareObject2(E a, E b, Comparator<? super E> c){   //利用比较器比较        return c.compare(a, b) > 0 ? true : false;    }}public class TestGenericDemo3 {    //定义三个匿名对象,专门对age进行排序    public static Comparator<Person> AGE_COMP = new Comparator<Person>() {    @Override    public int compare(Person o1, Person o2) {        // TODO Auto-generated method stub    return o1.age() > o2.age() ? 1 : (o1.age() == o2.age() ? 0 : -1);        }    };    public static void main(String[] args) {        // TODO Auto-generated method stub        //生成两个Person对象,调用compareObject进行比较        Person p1 = new Person("zhang", 20, "male");        Person p2 = new Person("liu", 21, "female");        System.out.println(GenericFunctional.compareObject(p1, p2));        //生成两个Student对象,调用compareObject进行比较        Student s1 = new Student("zhang", 20, "male", 98.5);        Student s2 = new Student("zhang", 20, "male", 98.5);        System.out.println(GenericFunctional.compareObject(p1, p2));

重点内容
三、泛型常见错误
(1)不能直接new泛型类型的对象 因为编译器不知道泛型类型T到底是什么类型? T a = new T();(即在使用时需给定类型)
(2)不能直接new泛型类型的数组,因为编译器不知道T是什么类型 ?T[] arr = new T[5]; => T[] array = (T[])new Object[5];
(3)static方法不能使用泛型类定义的泛型参数T呢?
因为static不需要对象来调用,是用类名来调用,而且类名调用不加参数类型,所以没法检测类型。
(4)不能定义泛型类的数组
GenericMath[] g3 = new GenericMath[5];
java的数组也是继承关系:
object[]是基类,因此object[]可以引用任何数组,就会出现数组中可以赋任意类型元素的错误。
所以在new数组是需类型强转:
T[] array=(T [] ) new object[[size]
(5)泛型代码需要检查需要制定上界?
public static int sumFunc3(T[] array){ }
(6)两个引用类型互相为继承关系,本来可以基类引用派生类对象的, 但是,该两个类型作为泛型类的实例化类型,互相是不能够引用的!


四、java的泛型通配符
(1)泛型通配符有上界也有界;
重点内容
通配符的上界是进行读,读取的类型是object类型;
通配符的下界是进行写,写入元素的形参类型写为通配符的下界;
不能用通配符定义对象;
(2)上界的应用:

public static int sumNumberStack(SqStack<? extends Number> stack){        int size = stack.size();        int sum = 0;        for(int i=0; i<size; ++i){            sum += stack.get(i).intValue();        }        return sum;    }}

(3)下界关键词super(意思是不能超过它,必须是它的基类
eg:

 SqStack <? super Number> s=new SqStack<object>();可以看到<? super Number>意思是一个未知的类型,但该类型是Number的基类,也就是说Number是该类型的下限
原创粉丝点击