簡體   English   中英

如何安全地將 java Object 轉換為泛型集合?

[英]How to cast java Object to generic collection safely?

我可以通過執行以下操作來安全地轉換簡單的 java 對象:

Object str = "test";
Optional.of(str)
      .filter(value -> value instanceof String)
      .map(String.class::cast)
      .ifPresent(value -> System.out.println("Here is the value: " + value));

但是我如何才能將對象轉換為通用集合呢?

例如:

Object entries = /**/;
// this is unsafe
List<Entry<String, String>> subscriptions = (List<Entry<String, String>>) entries;

我應該如何處理這樣的情況,是否有任何庫(類似於 ClassCastUtils)來幫助進行這種轉換?

沒有真正的好方法來做到這一點。 天真的方法是

  1. 檢查它是一個列表/集合/集合
  2. 檢查所有項目都是Entry s
  3. 檢查每個Entry所有鍵和值都是String s

例如

Map<String, String> map = new HashMap<>();
map.put("a", "b");
Object entries = map.entrySet();

boolean safe = Optional.of(entries)
    .filter(Set.class::isInstance)
    .map(e -> (Set<?>) e)
    .filter(set -> set.stream().allMatch(Map.Entry.class::isInstance))
    .map(e -> (Set<Map.Entry<?, ?>>) e)
    .filter(set -> set.stream().allMatch(e -> e.getKey() instanceof String && e.getValue() instanceof String))
    .isPresent();

然而,即使這樣也不能提供足夠的保證。 假設地圖被聲明為:

Map<String, Object> map = new HashMap<>();
map.put("a", "b");

在我們檢查時,這將被視為安全。 這是一個集合,所有條目當前都是字符串。 但是,如果其他一些代碼稍后會改變地圖,例如

map.add("b", 123);

然后你會意識到這個演員表仍然不安全。 您只能使用當前狀態,因此您無法對未來狀態做出任何保證。

您可以通過以下幾種方式解決此問題:

  1. 檢查后深拷貝整個集合。 但是在復制之前檢查過之后的競爭條件呢? 您將不得不使用鎖。
  2. 使地圖不可變

如果它是一個集合但它當前是空的呢? 在這種情況下,您無法對項目進行任何檢查。

正如您所看到的,與這樣的演員一起工作是一項非常艱苦的工作,並且有很多地方可能會出錯。 您最好的選擇是首先避免必須進行這樣的演員。

暫無
暫無

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

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