您的位置:首页 > 编程语言 > Java开发

JAVA泛型总结

2017-02-16 20:31 190 查看
最近复习了一下关于JAVA泛型方面的内容,在此做一下简单的总结,分一下几个方面介绍:

1、泛型带来的优点

2、泛型类泛型接口和泛型方法

3、通配泛型

4、泛型的限制

泛型简单的说,就是指参数化类型的能力,在未使用泛型之前,如ArrayList类,其中可以存放任意类型的对象,其方法大部分的参数类型都是Object类型,而实际中,我们常常仅需要存储一种类类型,如String类型,以方便进行String类型的操作,(String 类型和Integer类型若同时存于list中则很多操作都不行,如compareTo()方法,需要调用者和参数属于同一个类型)。

为了使容器存储同一种类类型,JAVA泛型机制很好的做到了这一点,不使用泛型,ArrayList对象可存储各种类类型,编译时不会报错,运行时有时会因不恰当的方法调用而出错,使用泛型机制,编译时就能够检测出这种错误.

1、优点:能够在编译时期检测出错误而不是运行时期,提高了程序的可靠性。

不需要强制类型转换就可以在ArrayList列表中提取出元素。

2、泛型类、泛型接口及泛型方法

class MyStack<T>{
private ArrayList<T> list=new ArrayList<T>();
public int getSize(){
return list.size();
}
public void push(T o){
list.add(o);
}
//取得栈顶元素而不出栈
public T peek(){
return list.get(list.size()-1);
}
//出栈操作
public T pop(){
T o=list.get(list.size()-1);
list.remove(list.size()-1);
return o;
}
public boolean isEmpty(){
return list.isEmpty();
}
}
泛型类的定义即在类名后用尖括号写上泛型符号如T、E(可理解为占位符)等,注意:泛型类的构造方法为 MyStack() 而不是MyStack<T>()
MyStack(){}   //正确的构造方法
MyStack<T>(){}  //错误的构造方法
泛型类里面的方法是带泛型类型的参数,而不是泛型方法,泛型方法的定义:在返回类型前面加上泛型类型
public class Main{
public static void main(String[] args){
Main.method("hello!");
}
//泛型方法:不一定要存在于泛型类中
public static <T> void method(T o){
System.out.print(o);
}
}
3、通配泛型

有点类似于JAVA的多态,通配泛型使得可以用泛型类型的子类或者父类类型来实例化泛型,总体分为三种:

<?>等价于<? extends Object>:非限定通配
<? extends T>:受限通配,表示可以接受T及T的子类型
<? super T>:下限通配,可接受T及T的父类型

这个应该不难理解,来一个稍微复杂一点的例子,使用泛型方法实现选择排序

public static <E extends Comparable<E>> void selectSort(E[] arr){
int index=0;
E min=arr[0];

for(int i=0;i<arr.length-1;i++){
min=arr[i];
index=i;

for(int j=i+1;j<arr.length;j++){
if(arr[j].compareTo(min)<0){
min=arr[j];
index=j;
}
}

if(index!=i){
E tempE=arr[i];
arr[i]=arr[index];
arr[index]=tempE;
}
}
}
<E extends Comparable<E>>表示泛型方法selectSort接受的参数类型为Comparable<E>类型或者它的子类类型,如当E为String类型时,Comparable<E>为Comparable<String>类型,而String类型正好为Comparable<String>的子类型,故可接受String类型的数组。

4、泛型的限制

泛型仅存在于编译时期,编译期间JAVA将会使用Object类型代替泛型类型,在运行时期不存在泛型;且所有泛型实例共享一个泛型类

public class Main{
public static void main(String[] args){
ArrayList<String> list1=new ArrayList<String>();
ArrayList<Integer> list2=new ArrayList<Integer>();
System.out.println(list1 instanceof ArrayList);//true
System.out.println(list2 instanceof ArrayList);//true
//System.out.println(list1 instanceof ArrayList<String>);//编译错误,不存在此类型
}
}虽然list1和list2属于不同的类型,但是JVM加载的类仅ArrayList,各泛型实例共享这个类;

泛型的4个限制:

(1)不能new  T()

(2)不能创建泛型数组:new T[];

但是可以使用强制类型转换的方法,不过编译器会给出一个警告。

T[] arr=(T[])new ArrayList[10];

(3)在静态环境下不能使用泛型类型的参数

如静态方法、静态变量、静态代码块都不能用泛型类型,原因在于各泛型实例共享一个类,而静态成员时随着类的加载就存在了的。

(4)异常类不能是泛型的。

总结:JDK1.5之后,很多原始类型都被重写成了泛型类或者泛型接口,如Comparable<T>接口、ArrayList<T>以及集合中其他很多的方法也都是带泛型类型的;泛型类型由于在存在类型消除,因此其兼容原始类型,如前面定义的泛型类MyStack,  MyStack与MyStack<Object>表面上看起来一样,实际上还是有区别的,前者是原始类型,后者是泛型的实例化。



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java arraylist 泛型