关于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);
为什么转换异常?
关于List泛型的强制转换的更多相关文章
- C#学习笔记二 (资源托管,泛型,数组和元组,运算符和类型强制转换)
托管和非托管资源 1.托管资源是指GC管理的内存空间,非托管资源是指文件句柄,网络连接,数据库连接等. 2.方法中临时申请的变量,被存放在栈中.栈存储非对象成员的值数据.例如在方法中有B b=new ...
- JAVA将数字字符串强制转换成整型变量----求参数之和实验代码(附流程图)
一.设计思想 先将参数个数输出,并利用循环结果将参数逐个输出,再将字符串强制转化成整型,利用循环结构相加求和 二.程序流程图 三.源程序代码 package demo; public class Co ...
- JS当心隐式的强制转换
JavaScript对类型错误出奇的宽容 3 + true; // 4 null + 3; // 3 运算符+(加号)的重载 运算符+既重载了数字相加,又重载了字符串连接操作.具体是数字相加还是字符串 ...
- C#高级编程笔记 2016年10月8日运算符和类型强制转换
1.checked和unchecked 运算符 C#提供了checked 和uncheckde 运算符.如果把一个代码块标记为checked, CLR就会执行溢出检查,如果发生溢出,就抛出overfl ...
- PHP是弱类型语言,自动转换,强制转换
强制转换: (int) - 转换成整型 (bool) - 转换.成布尔型 (float) - 转换成浮点型 (string) - 转换成字符串 (array) - 转换成数组 (object) - 转 ...
- Php中的强制转换详解
强制转换中分为两种,第一种就只临时转换,和永久转换.在临时转换中呢,首先可以通过第一中方式来显示,就是小括号的形式,临时转换成整型我们可以通过(int)都是这样的形式,或者是(integer)临时转换 ...
- c# 强制转换, 隐式转换, 显式转换
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...
- 黑马程序员-c语言-类型强制转换
强制转换的条件: 1.当所声明的类型不能满足所符值的变量时,需要转换声明的类型,以便能够存储变量. 例如:short存储的最大值为32767,但是所要符值大于32767时,short类型不符合,需要转 ...
- JavaScript学习笔记——数据类型强制转换和隐式转换
javascript数据类型强制转换 一.转换为数值类型 Number(参数) 把任何的类型转换为数值类型 A.如果是布尔值,false为0,true为1 B.如果是数字,转换成为本身.将无意义的后导 ...
随机推荐
- mysql创建用户和创建数据库赋值用户操作权限
mysql 进入mysqldb SELECT DISTINCT CONCAT('User: ''',user,'''@''',host,''';') AS query FROM mysql.user; ...
- 这个代码怎么改??Help快速排序 quicksort
#include<stdio.h>int a[101],n;void quicksort(int left,int right){ int i,j,t,temp; if(l ...
- HTML文件结构
转载(http://jingyan.baidu.com/article/75ab0bcbf04a75d6864db2fd.html) HTML文件结构 HTML文件均以<html>标记开始 ...
- 采用PHP函数uniqid生成一个唯一的ID
http://www.daimajiayuan.com/sitejs-17815-1.html
- Linux-SSL和SSH和OpenSSH,OpenSSL有什么区别
ssl是通讯链路的附加层.可以包含很多协议.https, ftps, ..... ssh只是加密的shell,最初是用来替代telnet的.通过port forward,也可以让其他协议通过ssh的隧 ...
- Unity3D深入浅出 - 新版粒子系统 (Shuriken) - Tonge
Shuriken粒子系统是继Unity3.5版本之后推出的新版粒子系统,它采用了模块化管理,个性化的粒子模块配合粒子曲线编辑器使用户更容易创作出各种兵分复杂的粒子效果. 创建一个粒子系统的方式有两种: ...
- 正则表达式 ——python 基础
一.引言 正则表达式是含有文本和特别字符的字符串,这些文本和特别字符描述的模式可以识别各种字符串. 正则表达式的强大之处在于特殊符号的应用,特殊符号定义了字符集合.子组匹配,模式重复次数...正是这些 ...
- C++运算符重载详解
1.什么是运算符重载 运算符重载是一种函数重载. 运算符函数的格式:operatorop(argument-list)例如,operator+()重载+运算符.其中的op,必须是有效的C++运算符,如 ...
- Linq的Distinct方法的扩展
原文地址:如何很好的使用Linq的Distinct方法 Person1: Id=1, Name="Test1" Person2: Id=1, Name="Test1&qu ...
- 微软发布了ASP.NET WebHooks预览版
微软 近期发布了ASP.NET WebHooks的预览版 ,这是一个可用于创建及使用Webhook功能的库.WebHooks支持MVC 5及WebApi 2. Webhook是一种通过HTTP实现用户 ...