泛型
来源:互联网 发布:大数据的结果展现方式 编辑:程序博客网 时间: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){
}
注意:泛型方法是在参数列表中返回值前面加泛型参数列表;
泛型方法举例1:public 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是该类型的下限
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 内部类与异常类:实验2
- C# DLL HRESULT:0x8007000B
- 【JZOJ 5484】 快乐树
- cadence vmanager(二)vmanager工作模式
- Unity Sample Project Tank!!!详解(零) Tank!!!简介
- 泛型
- 1030. 完美数列(25)
- 设计模式—观察者模式(不)
- 快速幂取模&扩展欧几里得算法
- Spring和MyBatis环境整合
- 一点一点学写Makefile(6)-遍历当前目录源文件及其子目录下源文件
- hadoop 常用命令
- 轻松搞定面试中的二叉树
- JVM菜鸟进阶高手之路十四:分析篇