【问题标题】:Type safety: Unchecked cast from Object to ArrayList<MyVariable>类型安全:从 Object 到 ArrayList<MyVariable> 的未经检查的强制转换
【发布时间】:2013-12-15 01:14:45
【问题描述】:

这是从服务器向客户端发送 ArrayList 的程序的一部分。我想删除这段代码最后一行的警告:

客户端代码:

Socket s;
(...)
// A server is sending a list from the other side of the link.
ois = new ObjectInputStream(s.getInputStream());
MyList = (ArrayList<MyVariable>) ois.readObject();

MyVariable 是一个具有一些属性的 Java 类。服务器正在创建一个 ArrayList 并用 MyVariable 变量作为项目填充它。然后它将完整的列表发送给客户端。

我想知道为什么我会有一个警告,以及如何完美地编写代码以获得 0 个警告。如果可能的话,我想避免使用“@SuppressWarnings("unchecked")”。 ;)

谢谢,

路易斯

【问题讨论】:

  • 通过套接字发送数组而不是集合。 (MyVariable[]) ois.readObject() 是一个安全的演员。要将 Collection 转换为类型化数组,请使用 list.toArray(new MyVariable[0])。要将数组转换为集合,请使用Arrays.asList 方法。

标签: java arraylist casting warnings unchecked-cast


【解决方案1】:

试试这个

Object obj = ois.readObject();
// Check it's an ArrayList
if (obj instanceof ArrayList<?>) {
  // Get the List.
  ArrayList<?> al = (ArrayList<?>) obj;
  if (al.size() > 0) {
    // Iterate.
    for (int i = 0; i < al.size(); i++) {
      // Still not enough for a type.
      Object o = al.get(i);
      if (o instanceof MyVariable) {
        // Here we go!
        MyVariable v = (MyVariable) o;
        // use v.
      }
    }
  }
}

【讨论】:

    【解决方案2】:

    无法避免此警告。 readObject() 返回一个对象。你需要投射它。并且强制转换为泛型类型总是会产生这样的警告。

    如果你想让你的代码尽可能干净,这是个好主意,但你应该尊重 Java 命名约定,并让变量名以小写字母开头。

    【讨论】:

    • 我很确定你可以。我的回答有没有漏掉什么?
    • 它不返回List&lt;MyVariable&gt;,而且是矫枉过正。 OP 应该知道发送的是 List&lt;MyVariable&gt;
    【解决方案3】:

    我不喜欢这样,但你可以有一个容器(某种别名或 typedef):

    // add "implements Serializable" in your case
    private static class MyVariableList {
        public List<MyVariable> value;
    }
    

    改为使用MyVariableList。这样你就可以显式地向编译器提供足够的信息来在运行时进行类型检查。

    【讨论】:

      【解决方案4】:

      我遇到了与 OP 类似的问题,并结合@VGR 的注释和用于数组的 Java 1.8 方法找到了一个很好的解决方案。

      我将根据 OP 的问题提供我的答案,因此它是通用的,希望对其他人有所帮助:

      1. 不是返回一个集合(列表),而是从服务器返回一个数组。在服务器端代码中使用以下代码将集合隐蔽到数组中:

        myVariableList.toArray(new MyVariable[0]);

        如果性能是上面的问题,可以使用以下,因此不需要调整数组的大小:

        myVariableList.toArray(myVariableList.size());

      2. 在客户端将对象数组转换为 MyVariable 类的数组。

        这是 JAVA 8 特有的。

        MyVariable[] myVarArr = Arrays.stream(ois.readObject()).toArray(MyVariable[]::new);

      3. 然后,最后将 Array 转换为 Collection(列表)。

        List&lt;MyVariable&gt; myList = Arrays.asList(myVarArr);

      谢谢。

      【讨论】:

        【解决方案5】:

        我也遇到过类似的情况,并且能够解决。 我的解决方案,应用于 OP 的例子是这样的:

        myList = (ArrayList<Someclass>) Arrays.asList( (Someclass[]) ois.readObject() );
        

        我已将命名约定(已经有人建议)更改为标准 Java(对象以小写字符开头),并且我已将 MyVariable 类重命名为 Someclass 以使其明确,这确实适用于任何类(而不仅仅是变量)。我还假设,类型为ArrayList&lt;Someclass&gt; 的服务器端上myList 的对应对象已作为数组Someclass[] 写入流。请注意,这很容易完成并且类似于 abhishek 已经建议的第一部分,但我的解决方案在最后一步有所不同:

        1. 我避免打电话给Arrays.stream
        2. 它更易于阅读,并被视为简单(无需进一步逻辑)和checked(不生成警告)演员表。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-02-03
          • 1970-01-01
          • 1970-01-01
          • 2016-01-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多