类型安全:未选中从Object转换为ArrayList <myvariable> </myvariable>

时间:2013-11-28 22:28:55

标签: java arraylist casting warnings unchecked-cast

以下是将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“)”。 ;)

谢谢,

路易斯

5 个答案:

答案 0 :(得分:19)

试试这个

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.
      }
    }
  }
}

答案 1 :(得分:13)

不可能避免这种警告。 readObject()返回一个Object。你需要施展它。而转换为泛型类型将始终产生这样的警告。

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

答案 2 :(得分:2)

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

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

MyVariableList合作。这样就可以明确地为编译器提供足够的信息,以便在运行时进行类型检查。

答案 3 :(得分:1)

我遇到了与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<MyVariable> myList = Arrays.asList(myVarArr);

  4. 感谢。

答案 4 :(得分:0)

我也遇到了类似的情况,并且能够解决它。 适用于OP示例的我的解决方案是:

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

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

  1. 我避免打给Arrays.stream
  2. 更容易阅读和快速理解为简单的(无需进一步的逻辑)和checked(不生成警告)强制转换。