Java-泛型

1.引言

        什么是泛型呢?举个例子(不举不行):

               钱包是用来放钱的。

               假如你的钱包里规定只能放钱(这就是泛型的作用了),那么你从你钱包里取出来的,不管是人民币、$、还是日元,它们都不用转换,因为它们都是-->“钱”;

               但是你的钱包里没有这个规定,里面什么都可以放,那么你从钱包里取出来的东西不一定是钱,假如是石头,那么你得把从钱包里的东西转换为钱,即将石头转换成钱。。。。。。这显然是错误的!

        所谓泛型,就是变量类型参数化。通过使用泛型,可以使编译时类型更安全,运行时更少抛出ClassCastException的可能。何为参数化,顾名思义就是将类型由原来的类型具体参数化。使用泛型若没有提供参数类型,即泛型没有参数化,系统可能会警告,此时类型为Object。

        泛型的第一个好处是编译时的严格类型检查。有效的避免了运行期的ClassCastException,提高了程序的安全性和健壮性。
这是集合框架最重要的特点。此外,泛型消除了绝大多数的类型转换。如果没有泛型,当你使用集合框架时,你不得不进行类型转换。另外 泛型简化了代码,应用泛型的程序提高程序的可读性,更利于团队的合作开发。

2.为啥要使用泛型?

        先看一段代码:

package cn.nuist.pers.September04;

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

public class GenericTest {

	public static void main(String[] args) {
		List list = new ArrayList();
		list.add("qq");
		list.add("we");
		list.add(123);
		for(int i=0;i<list.size();i++) {
			String name = (String) list.get(i);
			System.out.println("name:"+name);
		}
	}
}

        咱们再来看一下运行结果:

Exception in thread "main" name:qq
name:we
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
	at cn.nuist.pers.September04.GenericTest.main(GenericTest.java:14)

        在循环当中,由于忘记了之前的list中加入了Integer类型的值或是其他原因,很容易出现类似于上述的情况,在编译阶段正常,但是在运行时会抛出ClassCastException异常。当我们把一个对象放入集合中,集合不会记住对象的类型,当我们再次从集合中取出对象时,该对象的编译类型变成了Object类型,但其运行时仍是本身的类型,因此在String name处取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出现转化异常。

        泛型可以限制加入集合当中的元素类型,使编译是不出现问题,运行时就不会抛出ClassCastException异常。使用泛型的典型例子,是在集合中的泛型使用。

3.如何使用泛型

        在使用泛型前,存入集合中的元素可以是任何类型的,当从集合中取出时,所有的元素都是Object类型,需要进行向下的强制类型转换,转换到特定的类型。

比如:

List myIntList = new LinkedList();
myIntList.add(new Integer(0));
Integer x = (Integer) myIntList.iterator().next();

第三行的这个强制类型转换可能会在运行时产生错误。

泛型的思想就是由程序员指定类型,这样集合就只能容纳该类型的元素。

比如:

List<Integer> myIntList = new LinkedList<Integer>();
myIntList.add(new Integer(0));
Integer x = myIntList.iterator().next();

将第三行的强制类型转换变成第一行的List类型说明,编译器会为我们检查类型的正确性。这样,代码的可读性和健壮性就会增强。

        定义泛型方法时,必须在返回值前边加一个<T>,来声明这是一个泛型方法,持有一个泛型T,然后才可以用泛型T作为方法的返回值。

       Class<T>的作用就是指明泛型的具体类型,而Class<T>类型的变量c,可以用来创建泛型类的对象。

       为什么要用变量c来创建对象呢?既然是泛型方法,就代表着我们不知道具体的类型是什么,也不知道构造方法如何,因此没有办法去new一个对象,但可以利用变量c的newInstance方法去创建对象,也就是利用反射创建对象。

       泛型方法要求的参数是Class<T>类型,而Class.forName()方法的返回值也是Class<T>,因此可以用Class.forName()作为参数。其中,forName()方法中的参数是何种类型,返回的Class<T>就是何种类型。在本例中,forName()方法中传入的是User类的完整路径,因此返回的是Class<User>类型的对象,因此调用泛型方法时,变量c的类型就是Class<User>,因此泛型方法中的泛型T就被指明为User,因此变量obj的类型为User。

       当然,泛型方法不是仅仅可以有一个参数Class<T>,可以根据需要添加其他参数。

       为什么要使用泛型方法呢?因为泛型类要在实例化的时候就指明类型,如果想换一种类型,不得不重新new一次,可能不够灵活;而泛型方法可以在调用的时候指明类型,更加灵活。

参考资料:https://www.cnblogs.com/upcwanghaibo/p/5651168.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值