泛型浅析与应用

1.JAVA为什么要用泛型:

      泛型是在JDK1.5之后增加的,那么为什么要引用泛型这个支持呢?其实原因很简单:Java集合有个“缺点”---当你把一个对象“放进”集合之后,集合就会“忘记”这对象进来时候的数据类型,当我们需要再次取出该对象的时候,该对象的编译类型就变成了Object(这里需要提一下,其运行时的类型没有改变)。当我们需要取出其中的对象时候,需要进行强制类型转换,这样不仅会代码比较繁琐,也容易照成ClassCastExeception异常。

   (1)举一个例子:编译时不检查类型导致的异常

package javatest;
import java.util.ArrayList;
import java.util.List;
public class FanXing {
	public static void main(String[] args) {
		List strList=new ArrayList();
		strList.add("字符串1");
		strList.add("字符串2");
		strList.add(4);
		for(Object obj:strList){
			String str=(String)obj;
			System.out.println(str);
		}
	}
}
以上这段代码,在编译阶段是通过的,但是在运行阶段将会报ClassCastException异常,程序输出如下图:

这个错误原因时你将一个Integer对象“放进”了List集合中,运行时程序试图将Interger对象转换为String类型,所以报错。

(2)引入泛型就允许程序在创建集合时指定集合的元素类型,如List<String>,指这个List是String类型的,如果给这个List传值的时候,传入Interger类型的数字,在编译阶段就会报错,这样就使我们的代码更加健壮,也无需一些强制类型转换操作。如下面例子:

package javatest;

import java.util.ArrayList;
import java.util.List;

public class FanXing {
	public static void main(String[] args) {
		List<String> strList=new ArrayList<String>();
		strList.add("字符串1");
		strList.add("字符串2");
		//strList.add(4);
		for(String obj:strList){
			String str=obj;
			System.out.println(str);
		}
	}
}

2.为接口和类增加泛型声明

   (1)定义接口增加泛型声明

package javatest;
public interface List<T>{
	int add(T t);
}
在上面这个接口里面,T可以作为类型使用,在add方法中T可以作为参数类型使用。
 
    
 
    
 
    
 
    
 
    
 
    
 
    
 
    
 
   

   (2)可以为类增加泛型声明

public class FanXing<T>{	
		private T t;
		public FanXing(T t){
			this.t=t;
		}
           public T toInfo(){
              return this.t;
           }
	public static void main(String[] args) {
		FanXing<String> a=new FanXing("a");
		FanXing<Double> b=new FanXing(3.22);
	}
}

3.为带泛型声明的接口和类创建实现类或者派生子类

public class A extends FanXing<String>{
         public String toInfo(){
		      return "父类的返回值"+super.toString();
		 }
}
这里需要注意的是: 在泛型的使用中,定义方法时可以声明数据形参<T>,调用方法时必须为这些形参传入实际的数据如<String>。但是在使用类和接口时也可以不为形参<T>传入实际参数如<String>。下面举个例子:
public class A extends FanXing{
    return super.toInfo().toString();
}
上面的例子中,toInfo()返回的是Object类型

4.静态方法,静态初始化块或者静态变量的声明和初始化中不能使用泛型形参。


5.在instanceof引入泛型时,程序运行时会清除泛型的类型信息



                                                      这时可以使用通配符?解决这个编译异常。

6.类型通配符"?"

     先让我们看一个例子:
public class FanXing<T>{
		private T t;
		public FanXing(T t){
			this.t=t;
		}
		public static void ListTest(List<?> c){
			for(int i=0;i<c.size();i++){
				//省略代码
			}		
		}
}

其中List<?>代表这个List的元素类型是未知的,这个问号被叫做通配符,它的元素类型可以匹配任何类型。 一般来说带有通配符的类都是作为父类来使用。

7.泛型知识的展望

    其实泛型的基本常用知识介绍到这里已经差不多了,后续一些更深入的知识点如“设定类型形参的上限”等在平常日常开发中我没有运用到所以不做分析了。

8.贴一个泛型在实际项目中的运用

代码片段1:


代码片段2:


代码片段3:


猜你喜欢

转载自blog.csdn.net/qq_17586893/article/details/77688299