本节课主要讲解泛型的起因、泛型的概念,泛型类、泛型接口和泛型方法,以及泛型的安全和省心的作用。

起因

JDK1.4以前类型不明确,装入集合的类型都被当作Object对待,从而失去自己的实际类型;从集合中取出时往往需要转型,效率低,容易产生错误。

假设学生成绩有三种情况,有整数、小数、字符串,按之前存储可以使用ObjectObject可以接受任意类型,即多态。

/**
 * PO类 JAVABean
 * @author 裴新 
 */
public class Student {
   //成绩
   private Object javase;
   public Student() {
   }
   public Student(Object javase) {
      this.javase =javase;
   }
   public Object getJavase() {
      return javase;
    }
   public void setJavase(Object javase) {
       this.javase = javase;
   }
}

Object是所有类的根类,这种任意化在具体类使用的时候:需要类型检查;需要类型强制转换的;需要处理转换错误异常,非常麻烦!!! 

/**
 * 没有泛型的 类 存储数据 -->麻烦
 * @author 裴新
 *
 */
public class StuApp {
	public static void main(String[] args) {
	    //存入整数 int -->Integer -->Object
	    Student stu = new Student(80);	 
	    Object javase =stu.getJavase();
	    //类型检查  处理转换异常	
	    if(javase  instanceof Integer){
	      //强制类型转换
	      Integer javaseScore =(Integer) javase ;
	    } 
	    
	    stu =new Student("优秀");
	    javase =stu.getJavase();
	    //类型检查  处理转换异常	
	    if(javase  instanceof String){
	      //强制类型转换
	      String javaseScore =(String) javase ;
	    }	    
	}
}

解决方案:使用泛型,在定义集合的时候同时定义集合中对象的类型。使用泛型时,在实际使用之前类型就已经确定了,不需要强制转换。

概念

泛型就是参数化类型,如:可拆卸刀头的螺丝刀检查需要拧动的螺丝,根据螺丝选择适合刀头(一字、十字、星形),将正确的刀头插入到螺丝刀柄上后,您就可以使用螺丝刀执行完全相同的功能,即拧螺丝;泛型主要适用在集合中。

入门实例

/**
 * 泛型的入门 <>
 * 1、泛型: 标签 ,泛化类型
 * 2、作用: 省心  安全
 * @author 裴新
 */
public class Simple {
	public static void main(String[] args) {		
		List<String> list =new ArrayList<String>();
		//List<Integer>
		//安全
		//list.add(1); //类型检查
		list.add("so easy");
		//省心
		String ele =list.get(0);
		System.out.println(ele);
		
		//jdk1.4之前
		List list2 =new ArrayList();
		list2.add(1);
		list2.add("old");
		
		//取出数据
		Object obj =list2.get(0);
		//麻烦
		Integer num =(Integer)obj;
		//不安全
		//num =(Integer)list2.get(1);
		if(list2.get(1) instanceof Integer){ //手动类型检查
			num =(Integer)list2.get(1);//手动类型转换 才能安全
		}		
	}
}

作用

  • 模板:提高代码的重用率;
  • 安全:在编译的时候检查类型安全;
  • 省心:所有的强制转换都是自动和隐式的。

泛型类

定义类时使用泛型<>。定义模板:

class 类名<字母>{
        private 字母 属性名;
        setter与getter访问器
}		

注意

  • 泛型声明时字母不能使用 静态属性;
  • 泛型只能使用在引用类型,不能使用在基本类型上。

/**
 * 自定义泛型类 
 * 1、<> -->单个大写字母,尽可能见名知意 
 * 2、 
 * T Type 
 * K V Key Value 
 * E Element 
 * 3、注意点: 
 * 泛型不能使用在静态属性上
 * 指定的类型不能为基本类型
 * @author 裴新
 */
public class MyStudent<T> { //T-->Type类型
	private T javase;
	//泛型不能使用在静态属性上
	//private static T test; 
	public MyStudent() {
	}
	public MyStudent(T javase) {
		this.javase = javase;
	}
	public T getJavase() {
		return javase;
	}
	public void setJavase(T javase) {
		this.javase = javase;
	}
}

注意:自定义泛型的使用,在声明时指定具体的类型不能为基本类型。

/**
 *自定义泛型的使用
 * @author 裴新
 */
public class MyStuApp {
	public static void main(String[] args) {
		//MyStudent<int> stu =new MyStudent<int>();
		MyStudent<Integer> stu =new MyStudent<Integer>();
		//1、安全:类型检查
		//stu.setJavase("优秀");
		stu.setJavase(80);
		//2、省心:自动类型转换,免去了类型检查
		Integer score=stu.getJavase();
		System.out.println(score);
		
	}
}

泛型字母

通过上述的示例,我们认识了泛型字母。泛型字母即形式类型参数(formal type parameters )。

命名上可以随意指定,尽量使用单个的大写字母(有时候多个泛型类型时会加上数字,比如T1T2, 尽可能见名知意

常见的字母为:

  • T     Type
  • K V   Key Value
  • E     Element

这些字母类似于手机中的卡槽,在实际使用手机时放入具体的卡。也就是说当类被使用时,会使用具体的实际类型参数(actual type argument代替。

泛型接口

定义接口时使用泛型,与泛型类同理。

/**
 * 泛型接口
 * 泛型不能使用在全局常量上
 * @author 裴新
 */
public interface Comparator<T> {
	//全局常量
	/*public static final*/ int MAX_VALUE=1024;
	//公共的抽象方法
	/*public abstract */T compare(T t);	
}

注意:接口中泛型字母只能使用在方法中,不能使用在全局常量中。

泛型方法

定义声明方法时使用 <字母> ,泛型方法与所在的类是否为泛型类没有关系,如:

/**
 *自定义泛型方法的使用
 *定义: 在返回类型前面 <字母>
 * @author 裴新
 */

public class Method {
	//泛型方法
	public static <T> void test(T t){
		System.out.println(t);
	}
}

看个复杂的示例,为后面的课程内容做个引子:

/**
 * 非泛型类中定义泛型方法  复杂的示例
 * @author裴新
 *
 */
public class MethodDeep{
       public static <T extends List> void test(T t){
		System.out.println(t);
		t.add("aaa");
	}
	//释放资源
	public static <T extends Closeable> void test(T... a){
		for(T temp:a){
			try {
			   if(null!=temp){  
				   temp.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) throws FileNotFoundException {
		test("bjsxt is very good");
		test(new FileInputStream("a.txt"));
	}
}

上述示例看不懂没有关系,因为示例中使用了可变参数,可变参数在IO流中有具体的讲解;泛型中extends关键字在泛型深入中有具体的讲解。

总结

本节课我们主要学习了以下知识点:

  • 泛型概念:<> 泛化类型
  • 泛型作用:安全 省心
  • 自定义泛型
  • 1)、泛型类<字母,...>  T E K V
  •    只能用在成员变量上  只能使用引用类型
  • 2)、泛型接口接口<字母,...>
  •   只能用在抽象方法上
  • 3)、泛型方法: <字母,..> 返回类型|void

感谢大家的学习,记住我们的口号“弱者变强,强者更强”。

北京总部地址:北京市海淀区西三旗桥东建材城西路85号神州科技园B座三层尚学堂 咨询电话:400-009-1906 010-56233821
Copyright 2007-2014 北京尚学堂科技有限公司 京ICP备13018289号-1 京公网安备11010802015183