java基础加强_泛型

 

泛型

泛型是提供给java编译器使用的,让编译器挡住程序的非法输入,对于参数化的泛型,getClass返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的信息,只要跳过编译器,就可以往泛型集合中加入其它类型的数据,如:用反射得到集合,再调用其add方法即可


泛型的由来:
1,泛型的出现将运行时期的问题ClassCastException 转移到了编译时期变成了编译失败。
2,泛型的出现避免了类型强制转换的麻烦。
3,泛型技术是用在编译时期的技术。
4,泛型的出现提高了类型的安全性。

泛型特点:
参数化类型与原始类型的兼容性
1.参数化类型引用一个原始类型的对象,编译报告警告
2.原始类型可以引用一个参数化类型的对象,编译报告警告
参数化类型不考虑类型参数的继承关系。
在创建数据实例时,数组的元素不能使用参数化的类型。
泛型的?号通配符:限定了可以接受的参数类型,此时,有些类型的方法不可以使用,比如add方法。
泛型通配符的扩展:限定了通配符的上边界和下边界,指定通配符总是包括自己。
Vector<? extends Number> x = new Vector<Integer>();
Vector<? super Integer> x = new Vector<Number>();

泛型综合实例:
遍历时将Map变为Set,set实现了Iterable接口,详见代码泛型综合实例
泛型类型推断:
1.根据传递的参数类型或返回值进行判断。
2.如果参数中、返回值多处使用了同一种类型,那么确定为这种类型。
3.参数和返回值中出现多个类型,且无返回值,则去类型的最大公约数。

 

4.参数和返回值出现多个类型,方法调用中使用了多中类型,优先考虑返回值的类型。

 

练习代码:

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
/*
泛型是为了限定集合中存储对象的类型
 */
public class GenericTest {
	public static void main(String[] args) throws Exception {
		//创建一个String类型ArrayList
		ArrayList<String> al = new ArrayList<String>();
		al.add("abc");
		al.add("xyz");
		
		//创建一个Integer类型的集合
		ArrayList<Integer> al2 = new ArrayList<Integer>();
		al2.add(1);
		
		//虽然创建了两个不同类型的集合,但通过编译后,会去掉类型信息,所以他们的字节码是相同的
		System.out.println(al.getClass() == al2.getClass());
		
		//通过反射模拟add方法
		//虽然al2是一个Integer类型的集合,但还是打印出了String类型的值
		al2.getClass().getMethod("add",Object.class).invoke(al2, "abc");
		System.out.println("al2.get(1):"+al2.get(1));
		
		//演示:泛型中的通配符
		printCollection(al2);
		
		/*************泛型综合实例********************/
		//定义一个Map
		Map<String, Integer> maps = new HashMap<String, Integer>();
		maps.put("xcq", 23);
		maps.put("lxx", 23);
		
		//想要遍历出Map中的元素,需要先将Map转换成Set
		Set<Map.Entry<String, Integer>> entrySet = maps.entrySet();
		for(Map.Entry<String, Integer> en : entrySet){
			System.out.println("entrySet||"+en.getKey()+":"+en.getValue());
		}
		
		//实例:自定义泛型
		add(3,5);//T为int类型
		add("abc",3);//T为Object类型
		add(2.3, 3);//T为浮点类型
		
		//实例:交换数组中两个值的位置
		String [] str = new String[]{"abc","xyz","sss"};
		swap(str,0,1);
		for(int i=0; i<str.length; i++){
			System.out.println("array.str:"+str[i]);
		}
		//需注意,当数组为int类型时程序不能完成自动装箱,不能将int类型转换成Integer对象,
		//泛型的参数只能是引用类型,不能是基本数据类型
		
		
		/***************反射获得泛型的实际类型参数******************/
		
		//要获得泛型的实际类型,通过getClass()不能得到,可以通过Method方法中的属性获得
		//通过反射中的method方法获得applyMethod方法
		Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
		//获得applyMethod方法的类型
		Type types[] = applyMethod.getGenericParameterTypes();
		//通过方法的类型,获得参数类型
		ParameterizedType pType = (ParameterizedType) types[0];
		System.out.println("type1:"+pType.getRawType());
		//打印参数类型为Date
		System.out.println("type2:"+pType.getActualTypeArguments()[0]);
	}
	//applyMethod方法
	public static void applyVector(Vector<Date> t){
		
	}
	
	//交换两个任意类型数组中两个位置的值
	private static <T> void swap(T [] t, int i, int j) {
		T tmp = t[i];
		t[i] = t[j];
		t[j] = tmp;
	}
	
	//方法中参数配置为?,可以接受任意类型的对象进来。
	public static void printCollection(Collection<?> collection){
//		collection.add(2);//此处add方法会接收一个含有类型的参数,所以当合参数不匹配时容易报错。
		System.out.println("size:"+collection.size());//size方法中不含有类型相关的东西,可以使用,不用考


虑类型
		//循环遍历集合中的内容
		for(Object obj : collection){
			System.out.println("obj:"+obj);
		}
	}
	
	/****************实例:自定义泛型**********************/
	public static <T> T add(T x, T y){
		return null;
	}
}


Dao代码:

 

/*
 * 向数据库中添加对象时,想对某一个对象进行统一操作,比如定义crud方法进行操作时,可以确定操作的对象或返回的
 * 是同一个对象,可以在类后添加对象的标识。
 */
public class GenerateDao<E> {
	public void add(E x){
		
	}
	public E findById(int id){
		return null;
	}
	public void delete(E obj){
		
	}
	public void update(E obj){
		
	}
	public Set<E> findByConditions(String where){
		return null;
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值