簡體   English   中英

類型安全:從 Object 到 ArrayList 的未經檢查的強制轉換<MyVariable>

[英]Type safety: Unchecked cast from Object to ArrayList<MyVariable>

這是將 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")”。 ;)

謝謝,

路易斯

試試這個

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

無法避免此警告。 readObject()返回一個對象。 你需要投射它。 並且轉換為泛型類型總是會產生這樣的警告。

如果你想讓你的代碼盡可能干凈,這是一個好主意,你應該尊重 Java 命名約定,並讓變量名以小寫字母開頭。

我不喜歡那樣,但是您可以擁有一個容器(某種別名或 typedef):

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

並使用MyVariableList代替。 這樣你就明確地向編譯器提供了足夠的信息來在運行時進行類型檢查。

我遇到了與 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);

謝謝。

我也遇到了類似的情況並且能夠解決它。 我的解決方案,適用於 OP 的例子是這樣的:

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

我已將命名約定(如某人建議的那樣)更改為標准 Java(對象以小寫字符開頭),並且我已將 Class MyVariable重命名為Someclass以使其明確,這確實適用於任何類(而不是只是變量)。 我還假設,類型為ArrayList<Someclass>的服務器端myList的相應對象已作為 Array Someclass[]寫入流。 請注意,這很容易完成,類似於 abhishek 已經建議的第一部分,但我的解決方案在最后一步有所不同,因為:

  1. 我避免調用Arrays.stream
  2. 它更容易閱讀並被快速感知為一個簡單(沒有進一步的邏輯)和checked (不生成警告)的強制轉換。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM