代码之家  ›  专栏  ›  技术社区  ›  brienna

如何将未选中的强制转换对象寻址到ArrayList<Vehicle>

  •  3
  • brienna  · 技术社区  · 8 年前

    对于一个类,我被指定编写代码来读取该类的对象 Vehicle 使用ObjectInputStream( in ). 这些对象存储在一个名为 orders .

    SSCE:

    // Read all orders
    Object obj = in.readObject();
    orders = (ArrayList<Vehicle>) obj;
    

    然而,编译器抱怨:

    MacBook:Homework Brienna$ javac Orders.java -Xlint:unchecked
    Orders.java:152: warning: [unchecked] unchecked cast
                        orders = (ArrayList<Vehicle>) in.readObject();
                                                                    ^
      required: ArrayList<Vehicle>
      found:    Object
    1 warning
    

    我总是尝试改进代码,而不是忽略或抑制警告。在这种情况下,我已经想出了一个解决方案,但我正在努力理解它为什么有效,以及是否有更好的解决方案。

    此更新将停止警告:

    // Read all orders, casting each order individually
    Object obj = in.readObject();
    ArrayList ar = (ArrayList) obj;
    for (Object x : ar) {
        orders.add((Vehicle) x);
    }
    

    根据我所读到的内容,它之所以有效,是因为 (ArrayList<Vehicle>) obj 如果不是所有元素都是 交通工具 . 我很困惑——即使ArrayList的类型参数被指定为 交通工具 ? 此外,是否有更好的解决方案,例如使用 instanceof ?

    2 回复  |  直到 8 年前
        1
  •  5
  •   VGR    8 年前

    你很接近。投球总是安全的 ArrayList<?> :

    Object obj = in.readObject();
    ArrayList<?> ar = (ArrayList<?>) obj;
    
    orders.clear();
    for (Object x : ar) {
        orders.add((Vehicle) x);
    }
    

    您甚至可能希望更加安全,并将其转换为更一般化的内容,如Iterable:

    Object obj = in.readObject();
    Iterable<?> ar = (Iterable<?>) obj;
    
    orders = new ArrayList<>();
    for (Object x : ar) {
        orders.add((Vehicle) x);
    }
    

    如果您可以控制最初序列化的对象,那么有一种方法可以完全避免循环:使用数组而不是集合。数组类型始终是安全强制转换(如果它们本身没有泛型类型):

    Object obj = in.readObject();
    orders = new ArrayList<>(Arrays.asList((Vehicle[]) obj));
    
        2
  •  1
  •   serdroid    8 年前

    第一段代码使用generic(ArrayList)摘录演员阵容 第二段代码摘录了演员阵容,没有泛型。 cast是一种运行时检查-java编译器执行类型擦除,在运行时 List<Vehicle> List<Car>