关于List泛型的强制转换

当我们从数据库中查询出一些数据,有时返回的结果可能是List<Object>类型,而我们清楚的知道它的准确类型是List<User>,可能我们想直接的去进行类型的转换,你可能会这么写:

//DbUtils.list("from User")返回是List<Object>类型

List<User> listUser= (List<User>)DbUtils.list("from User");

然而编辑器提示不可转换,这是为什么啊?我们项目开发中常常像下面这样去使用强转都可以的啊:

Object o= new Object();

User u= new User();

//向下转型

u= (User)o;

o= u;

看看上面的代码,是很正常的转换啊,即使父类向下转型为子类也是没问题的尽管存在类型安全的隐患,以下为我的推算,因为Object是所有类型的父级,所以任何对象都可以去转换成Object,因为有了这个继承的特性,有可能Object指向了一个User,而我们又需要使用这个User的方法,所以它支持存在安全隐患的强制向下转型,尽管存在安全隐患,但只要我们编码时稍微注意就可避免此隐患,因为我们知道这个Object指向的是一个User,所以有继承关系的向下类型转换是可避免的安全隐患。

但为什么List<User>和List<Object>转就不行了呢?

我们可以把List<User>和List<Object>想象为两个特殊(类似基本类型的存在)的类型(此处暂不知道如何解释,因为我对java的底层泛型处理这块知识并不了解,暂时先去这么理解),就例如:

String s= "a";

Integer i= 12;

i= (Integer)s;

你会发现字符串不能强转到整形,编译器禁止这么做是为了让类型更加安全,如果任何类型之间都能互相转换的话那将会导致类型的不安全,因为他们之间没有继承关系,如果贸然去转换将会发生不可避免的类型安全隐患,但是他们的父类都是Object,我们可以通过使用Object作为桥梁来间接转换:

String s= "a";

Integer i= 12;

Object o= s;

i= (Integer)o;

这样虽然编译期并没有报错,但运行期将会报类型转换异常,所以我们使用时一定要小心,只能强转给它的原类型。

 

既然我们无法直接转换,而又不想一个元素一个元素的去转类型,那么我们就间接的去转换吧,下面是间接转换的几种方式:

//1,此方法不可行,虽然编译期不报错,但运行期会转换失败,数组转换失败的原因与泛型强转失败应该同理,都是特殊(类似基本类型的存在)的类型,数组的强转在编译期检查不出来,使用的时候要注意这点。

List<User> listUser= Arrays.asList((User[])DbUtils.list("from User").toArray());

//2

List<User> listUser= Arrays.asList(DbUtils.list("from User").toArray(new User[0]));

//3,此方法不可行,虽然编译期不报错,但运行期会转换失败,数组转换失败的原因与泛型强转失败应该同理,都是特殊(类似基本类型的存在)的类型,数组的强转在编译期检查不出来,使用的时候要注意这点。

List<User> listUser= new LinkedList<User>();
Collections.addAll(listUser, (User[])DbUtils.list("from User").toArray());

//4

List<User> listUser= new LinkedList<User>();
Collections.addAll(listUser, DbUtils.list("from User").toArray(new User[0]));

//5,利用万物皆Object的思想来使用强转

List<User> listUser= (List<User>)(Object)DbUtils.list("from User");

 //6

Object object= DbUtils.list("from User");
List<User> listCart= (List<User>)object;

我比较喜欢2和4的转换方式。

注意:基本类型的强转和引用类型的强转是有区别的,但这种区别很好区分,下面举一个小例子:

//1

int i= 1;

long l= 10;

//可行

i= (i)l;

//2

Integer i= new Integer(1);

Long l= new Long(10);

//不可行

i= (Integer)l;

 

以上观念为经验总结,并非总是正确的,如果你感觉我的见解有误,请及时纠正我。

求解释:

Object[] os= new Object[]{"a","b","c"};
String[] ss= (String[]) os;
System.out.println(ss);

即使利用万物皆对象的思想也是一样的结果。

Object[] os= new Object[]{"a","b","c"};

Object o= os;
String[] ss= (String[]) o;
System.out.println(ss);

为什么转换异常?

 

转载于:https://www.cnblogs.com/hihtml5/p/6194460.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java中,是一种编译期技术,因此在编译器看来,你自己定义的是真实存在的类,和其他类(如String、Integer等)没有区别。因此,当你将赋给其他变量时,编译器会自动进行类转换。这种自动转换是通过查看字节码来实现的,其中会被擦除成原始类(raw type)。实际上,的成功离不开多态的支持。多态允许在运行时通过父类引用指向子类对象,从而实现对不同类的自动转换。所以,的智能转换依赖于多态的支持。总的来说,Java的强制转换是通过编译器进行的,它依赖于多态的支持,并且在编译期间进行类擦除。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [java基础进阶六-](https://blog.csdn.net/qq_45891099/article/details/124845542)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Java 深入理解强制及自动转](https://blog.csdn.net/doncoder/article/details/90734268)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值