zoukankan      html  css  js  c++  java
  • 关于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);

    为什么转换异常?

  • 相关阅读:
    网络测量中基于Sketch方法的简单介绍
    Reading SBAR SDN flow-Based monitoring and Application Recognition
    Reading Meticulous Measurement of Control Packets in SDN
    Reading SketchVisor Robust Network Measurement for Sofeware Packet Processing
    ovs加dpdk在日志中查看更多运行细节的方法
    后缀数组
    (转载)LCA问题的Tarjan算法
    Codeforces Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) A. Checking the Calendar(水题)
    Vijos 1816统计数字(计数排序)
    卡特兰数
  • 原文地址:https://www.cnblogs.com/hihtml5/p/6194460.html
Copyright © 2011-2022 走看看