黑马程序员 学习日记(八)

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------

泛型的应用

泛型是Java1.5的新特性,,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。

1.集合中的泛型

class GenericDemo
{
	public static void main(String[] args)
	{
		ArrayList arrayList = new ArrayList() ;
		arrayList.add(1) ;
		arrayList.add(1l) ; //注意,数字1后面是字母L的小写

		int i = (int)arrayList.get(1) ;
	}
}
以上代码运行一次会报错
Exception in thread "main" java.lang.ClassCastException: java.lang.Long cannot b
e cast to java.lang.Integer
        at GenericDemo.main(ClassLoadDemo.java:26)
可以看出,整数型转换失败,集合中取出的是长整型,并不是我预期的int。
之所以会出这样的问题,是因为在往集合添加对象时没有一个规范的准则。我们就会希望一个集合我只想让它收集字符串对象。泛型可以帮到我们。
ArrayList<String> al = new ArrayList<String>() ;
按上面这行代码去定义一个集合,在添加元素时你就必须只能添加String类型的对象,想al.add(1) 这么做编译器就会报错,不予通过。这样我们就规定了一个泛型。这一句的泛型命名规则很简单,就把它看作把类名变长了,类名后面追加类型参数,参数用<>包围起来。
如果是有多个数据的哈希类集合,有几个数据就在<>写几个数据对应的类型,中间用“,”英式逗号隔开,如下代码:
HashMap<String,Integer> map = new HashMap<String,Integer>() ;
也是比较容易理解的,这里就不再过多演示。

但是通过map可以衍生出另一个知识,就是entry。entry是用来遍历map用的。因为map这个接口本身是没有迭代方法,需要向上转为set,set有iterator方法。entrySet()方法是map转为set的途径,entrySet()会返回装有Map.entry的set。听到这里,也许会有点难以理解,需要记住的就是想要迭代map,找一个方法让它成为set。
怎么把map变为set呢
class GenericDemo
{
	public static void main(String[] args)
	{
		HashMap<String,Integer> map = new HashMap<String,Integer>() ;
		map.put("Tom",22) ;
		map.put("Jarry",11) ;
		map.put("Join",66) ;

		map.entrySet() ;
	}
}
首先map.entrySet()得到所有数据包装为entry,再用set对象的entry去接收,因为map有泛型,这个entry也必须保持一样的泛型。所以就得到以下代码:
class GenericDemo
{
	public static void main(String[] args)
	{
		HashMap<String,Integer> map = new HashMap<String,Integer>() ;
		map.put("Tom",22) ;
		map.put("Jarry",11) ;
		map.put("Join",66) ;

		Set<Map.entry<String,Integer>> entrySet = map.entrySet() ;
	}
}
Map.entry提供了getKey和getValue两个方法读取map里的数据,接下来一个简单的for循环就能把entrySet全部迭代出。代码里不好理解的也就一个嵌套泛型,
Set<Map.entry<String,Integer>>   从外往里看,先规定set只放entry,放什么样的entry呢?再规定是String,Integer的entry。通俗的比喻,一个车只能坐帅哥,帅哥可能是来自美国来自法国来自中国,现在司机只喜欢中国帅哥!

2.方法中的泛型

集合中的泛型最为直观易懂,有了这样的一个入门,再来看有些难度的方法泛型就更加容易理解。方法中的泛型,比较常见的使用方式是通配符。可以在API文档里经常看到Class后面跟有一个泛型标记<>,但是尖括号里面却是一个问号或者一个字母,它代表着可以接受任意类型的参数,这就是通配符。出一个题目,怎样打印任意一个参数化的集合?例如,同一个方法传递这几个collection<Integer>,collection<String>,collection<Object>实参都可以打印。
public static void printCollection(Collection<?> collection)
	{
		for (Object obj : collection)
		{
			System.out.println(obj) ;
		}
	}
一个问号就代表这里是未知的,可以理解为属于泛型里的特殊变量,你传过来是什么问号就变为什么,再利用Object打印出来。
注意:因为你不知道collection会是一个什么参数化的集合,所以你也无法执行确定类型的操作,比如add("string")这样添加元素的方法,只能执行无关类型的方法,collection.size()这种可以执行。
有些情况,虽然你希望接收任意参数,但只想要关于数字的不要String,这时可以通过限定上下界来实现。
ArrayList<? extends Number>        上边界,接收Number以及子类
ArrayLIst<? super  Integer>                下边界,接收Integer以及父类

如果想要返回值呢
public static <E> E getSum(E a,E b)
	{
		return a+b ;
	}
方法声明没有写错,但是a+b是错的,还是那个原因,因为是未知的,你不能进行关于类型的操作。改为return null ;就没错了。E只能是引用类型,基本类型是不可以的。int可以自动装箱Integer,但是int[]数组就不会,用这个传给E就会出错。

3.类的泛型

class DAO<E>
{
	public void create(E e)
	{
            //接收任意类型数据
	}

	public E check(int id)
	{
            //可以把E返回
	}
        public Set<e> getCollection(String where)
        {
            //可以返回集合
        }
}</e>

在类名旁边定义一个泛型,整个类里就可以应用此泛型。。。在使用对象时可以这样定义。
DAO<Class> dao = new DAO<Class>()
调用 create 方法时,必须传递 Class 类型数据,调用 check 时返回一个 Class 类型数据必须用 Class 对象接收。
另外,静态方法不能用泛型,泛型只针对new出来的对象实例。

总结

泛型还有很多巧妙的用处,这里没有办法一一全部阐述。有了泛型既可以规范一些内容,也可以不规范内容,可以说为开发带来的方便非常之多。
如有什么特别的使用方法还请不吝赐教!
互相学习互相进步!!


---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值