处理泛型时遇到的问题和个人理解

泛型类和泛型方法

泛型类就是在类名右边加 < T >,表明这是一个泛型类,方法这是在public后面加一个< T >表明这是一个泛型方法
下面展示一些 class <T>

class X<T>

下面这个是泛型方法,返回一个泛型类型。

public <T>  T test(){}
下面是我遇到的问题。

在这里插入图片描述
我有一个User的bean,然后创建了dao类,创建一个user的dao实现类,就是userDaoImpl类,然后使用的是dbutil的库,用queryrunner来实现查询插入删除。get方法是返回的是user的单个bean,使用的是beanhandler这个类,然后为了统一给beanHandler传入User的class,我就在类中创建了一个。

 Class userClass=null;

并在无参构造函数中初始化这个Class对象。

 userClass=User.class;

这个query方法,返回的类型是根据Beanhandler这个类来决定的,简而言之,这里的query方法返回的是一个User对象,但是这里编译前却出现的了错误,编译器说query返回的是Object对象,然后我强转后去调试,发现返回的就是User对象。这就是问题所在。实际运行时返回的是User对象,但是编译时却是Object对象。

主要的问题就是这个userClass了,Class对象本身是带泛型的,我这里并没有写上泛型,导致Class会默认泛型为Object,所以传到Beanhandler里面时,Beanhandler的泛型也变成了Object,本身泛型就是在编译时起作用,并不会管你的这个Userclass里面存的是什么对象,所以这就是为什么编译出问题,实际调试返回的是Object,因为编译时,发现泛型是Object,返回的是Object,所以要求我强转,但是实际运行时,使用的是userClass指向的这个User.class对象,通过反射创建实例,所以返回的是User。
解决方案有三种:

一、 Class<User> userclass=null;

第一种是因为我设置了Class的泛型就是User,这样给构造器传进去的Class的泛型就是User,而不是Object,这样给泛型类的泛型就赋值了User。

二、 queryRunner.query(connection,sql, new BeanHandler<User>(userClass),args);

第二种就是通过泛型类来解决,直接给泛型类的泛型赋值User就好了。

三、 queryRunner.query(connection,sql, new BeanHandler<>(User.class),args);

第三种就是直接拿到User.class给BeanHandler的构造器的参数赋值,因为User.class返回的就是Class< User >这样的Class对象,已经带上了泛型的Class对象。
##java编译和运行的区别

java编译和运行的区别

上面的问题可以用一个例子简化而来。
在这里插入图片描述

定义一个泛型方法,传进一个带泛型的Class对象,然后返回这个Class对象的实例,正常来说,是可以运行的,传入的是User的Class对象,返回的是User的实例,那么用User接收也没有问题,但是为什么这个方法却说我返回的是Object类型呢。
这就涉及到了java的泛型作用范围了。
Java程序的启动,分成编译和运行,编译由编译器完成,运行由JVM运行。
编译的实际过程可以在网上查到,这里解释编译的主要作用:编译主要就是为了检查我们代码的语法,确保我们的java程序没有语法错误,然后将.java文件变成.class字节码文件。泛型就是在编译期起作用,运行时不起作用,因为运行时会将泛型擦除掉,泛型擦除的问题下面会解释。
回到这里的问题。User.class会返回一个class< User>对象,然后再赋给cls这个Class对象,但是注意,cls这个Class对象并没有指定泛型,所以他的默认泛型会是Object,然后再调用give方法,将cls对象传进去,这里就出问题了,cls的默认泛型是Object,然后用这个泛型创建了一个实例并返回,这个实例的类型就是Object,所以才会有编译的问题,编译器告诉我们要强转为User类型。
解决方法有两种,一就是指定cls的泛型为User,二就是不通过cls这个对象传值,直接用User.class传值,因为User.class就是class< User>,也指定了泛型。
那么怎么知道泛型是只在编译期起作用呢。我们将 User user=a.give(cls)强转一下,保证可以运行,然后在调试时观察方法返回的到底是什么。

User user=(User)a.give(cls)

在这里插入图片描述
调试的时候,选择停留在return语句这里,可以看到返回的就是User对象,并不是编译时说的Object对象,这是因为运行的时候,实际生成的对象是根据这个clazz形参来决定的,不是根据T这个泛型。

我们可以总结的就是,泛型就是只在编译期起作用,泛型的根本目的就是为了我们在写代码的时候,可以检查出类型错误,而不是到了运行期,出了问题才解决。

泛型擦除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值