javase 泛型

1 好处:

泛型:

在编译时检查类型安全

所有的强制转换都是自动和隐式的,不需要手动强制转换类型。

2 应用地方:

2.1  泛型典型应用,  泛型声明类参数类型

/**
 * 泛型类:声明时使用泛型
 * 字母:
 * T  Type 表示类型。 
	K V 分别代表键值中的Key Value。 
	E 代表Element。 
 使用时确定类型
 注意:
 1、泛型只能使用引用类型,不能基本类型
 2、泛型声明时字母不能使用 静态属性|静态方法上
 * @author Administrator
 *
 * @param <T>
 */
public class Student<T1,T2> {
	private T1 javaScore;
	private T2 oracleScore;
	
	//泛型声明时不能使用 静态属性|静态方法上
	//private static T1 test;

	public T1 getJavaScore() {
		return javaScore;
	}

	public void setJavaScore(T1 javaScore) {
		this.javaScore = javaScore;
	}
	
	public T2 getOracleScore() {
		return oracleScore;
	}
	
	public void setOracleScore(T2 oracleScore) {
		this.oracleScore = oracleScore;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//使用时指定类型(引用类型)
		Student<String,Integer> stu = new Student<String,Integer> ();
		//1、安全:类型检查
		stu.setJavaScore("优秀");
		//2、省心:类型转换
		int it =stu.getOracleScore(); //自动拆箱 不需要人工强制转换 
	}

}

2.2 泛型声明接口参数类型 

public interface Comparator<T> {
	void compare(T t);	
}

2.3 泛型用在方法形参中声明类型, 在真正调用方法传递真正参数时,才知道这个方法形参具体类型

public class TestMethod {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		test("a"); //T -->String
	}
	//泛型方法
	public static <T> void test(T a){		
		System.out.println(a);
	}
	// extends <=
	public static <T extends Closeable> void test(T... a){		
		for(T temp:a){
			try {
				if(null!=temp){
					temp.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

2.4 泛型在父子类的使用 :

package com.bjsxt.gen03;
/**
 * 父类为泛型类, 
 泛型用在
 * 1、属性
 * 2、方法
 * 
 * 要么同时擦除,要么子类大于等于父类的类型,
 * 不能子类擦除,父类泛型
 * 1、属性类型,  属性随位置而定 在哪里定义的就跟着哪块类型
 *  属性定义在父类中,随父类而定
 *  属性定义在子类中,随子类而定, 如果同名属性出现在了父类和子类中并且使用不同的泛型,那么子类使用中这个属性跟随子类泛型类型
 * 2、方法重写时:
 *  方法中形参的泛型随父类而定
 * 
 * 
 * @author Administrator
 *
 * @param <T>
 */
public abstract class Father<T,T1> {
	T name;
	public abstract void test(T t);

}
/**
 * 子类声明时指定具体类型
 * 属性类型为具体类型
 * 方法同理
 */
class Child1 extends Father<String,Integer>{
	String t2;
	@Override
	public void test(String t) { // 方法中形参的泛型随父类而定,父类中定义方法test(T t)在子类继承时,明确指定第一个形参为String,那么这个重写的方法的参数就是String
		this.name = ""; // name属性是定义在父类中的 
	}	
}
/**
 * 子类为泛型类 ,类型在使用时确定,子类的泛型可以扩展
 * @author Administrator
 *
 */
class Child2<T1,T,T3> extends Father<T,T1>{
	T1 t2;
    T1 name; // 同名属性出现在父类和子类中,那么name跟随子类泛型走
	@Override
	public void test(T t) {
		
	}
}
/**
 * 子类为泛型类,父类不指定泛型类型时,父类的泛型的擦除(失效),父类中原来定义的泛型r<T,T1>会使用Object替换掉
 */
class Child3<T1,T2> extends Father{
	T1 name2;
	@Override
	public void test(Object t) {//父类的方法跟随父类的泛型 这里父类泛型给擦除掉 因此形参就是Object 不会跟随子类走
		// TODO Auto-generated method stub		
		Object object = this.name; // 可以使用eclipse查看 this.name返回的类型是Object 
	}
	
}
/**
 * 子类与父类同时擦除, 就是子类和父类都不使用泛型了 
 */
class Child4 extends Father{
	String name;	
	@Override
	public void test(Object t) {
		
	}
	
}
/**
 *错误:子类擦除,父类使用泛型
class Child5 extends Father<T,T1>{
	String name;	
	@Override
	public void test(T t) {
		
	}
*/
	

2.5 泛型 ?的使用 

/**
 * 通配符
 * ?类型不定,使用时确定类型
 * ?使用:声明类型|声明方法上,不能声明类或使用时
 * ? extends : <= 上限  指定类型 子类或自身
 * ? super :>=下限   指定类型 为自身或父类
 * @author Administrator
 *
 */
public class Student<T> {
	T score;
	
	
	
	
	public static void main(String[] args) {
		Student<?> stu = new Student<String>(); //  =左侧是声明泛型, =右侧是使用时,在使用时不能使用?
		test(new Student<Integer>()); // 
		
		test2(new Student<Apple>());
		//test3(new Student<Apple>()); //泛型没有多态	, 打开注释时会编译报错,	
		
		//test4(new Student<Apple>()); //< 编译不通过 
		 stu  = new Student<Fruit>();;
		//test4(stu); //使用时确定类型  编译不通过 
		test4(new Student<Object>());
		test4(new Student<Fruit>());
		
	}
	
	public static void test(Student<?> stu){
		
	}
	public static void test3(Student<Fruit> stu){
		
	}
	// <=
	public static void test2(Student<? extends Fruit> stu){
		
	}
	//>=
	public static void test4(Student<? super Fruit> stu){
		
	}
	
}

2.6 没有泛型数组 

/**
 * 没有泛型数组
 * 声明可以使用,但是创建失败
 * @author Administrator
 *
 */
public class Array {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Integer[]  arr = new Integer[4]; 
		//Student<String>[] arr2 = new Student<String>[10];
		Student<?>[] arr2 = new Student[10];
		
		MyArrayList<String> strList =new MyArrayList<String>();
		strList.add(0, "a");
		String elem =strList.getElem(0);
		System.out.println(elem);
		
		
	
		
	}

}
class MyArrayList<E>{
	//E[] cap =new E[10]; 没有泛型数组, = 左侧可以声明,但是 =右侧如果使用时 编译失败,因此 没有泛型数组 
	Object[] cap = new Object[10];
	
	public void add(int idx,E e){
		cap[idx] =e;
	}
	
	
	@SuppressWarnings("unchecked")
	public E[] getAll(){
		return (E[]) cap;
	}
	@SuppressWarnings("unchecked")
	public E getElem(int idx){ // 没有泛型数组  在获取时强制进行类型转换 并添加注解 压制警告 
		return (E) cap[idx];
	}
}

2.7 jdk1.7中对泛型的改进 :

/**
 * 1.7中使用泛型,声明一次类型即可
 * 在使用|创建时不用指定类型
 * @author Administrator
 *
 */
public class Test7 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		List<String>  arrList= new ArrayList<String>(); // jdk1.6和以下版本下定义方式
		List<String>  arrList2= new ArrayList<>(); // jdk1.7时, 只需要声明一次即可 
	}

}

猜你喜欢

转载自chengjianxiaoxue.iteye.com/blog/2398671