![](/img/trans.png)
[英]Java: Generic type casting, how can I fix this so I don't suppress the unchecked warning
[英]How can I use Java Generic to suppress the warning?
在下面的代碼中,
在設備 class 的更新方法中為泛型類型字段分配值時出現警告。
如何修復它以獲得正確的代碼?
@Getter
@Setter
public class Device<T> {
private boolean updated;
private T value;
private Date updatedAt;
public void update(Device<?> p) {
this.value = (T) p.getValue(); // unchecked case warning
this.updatedAt = p.getUpdatedAt();
this.updated = true;
}
}
Map<DeviceName, Device<?>> currDevices= getDevices(...);
Map<DeviceName, Device<?>> newDevices = getNewDevices(...);
for (DeviceName name : currDevices.keySet()) {
Device<?> device = currDevices.get(name);
Device<?> newDevice = newDevices.get(name);
if (device.getUpdatedAt() == null || device.getUpdatedAt().before(newDevice.getUpdatedAt())) {
// If I modify the device.update method -> public void update(Device<T> p) {
// An error occurs here.
device.update(newDevice);
}
}
當您編寫(T) foo
時,其中 T 是 generics 類型變量,您正在進行類型斷言。 如,這是一個字面上的無操作。 那永遠不會拋出ClassCastException
並且不會轉換任何東西。 然而,它可能不是一個T
(你只是告訴編譯器:我確定它是,基於我這么說),這意味着其他地方,很久以后,也許是一個不同的線程,一個ClassCastException
即使你沒有投射任何東西,也會發生。
解決方案通常是在括號中有任何類型的 var 時永遠不要使用強制轉換運算符。
在這里,這是一件簡單的事情:使那個Device<? extends T> p
Device<? extends T> p
而不是Device<?> p
,很容易。 大概是有道理的: A Device<Number>
不能用Device<String>
更新; 你需要一個Device<Number>
或者一個Device<Integer>
。
Map<DeviceName, Device<?>> currDevices= getDevices(...);
這就是所謂的異構map; 將DeviceName
映射到許多不同類型的 map。 Java 不喜歡這些,通常這意味着您現在致力於這些警告。 如果不完全重寫此代碼的工作方式,就無法擺脫它們。 map 需要以某種方式離開 go。 Java 絕對無法驗證currDevices.get("foo")
返回與newDevices.get("foo")
("foo") 相同類型的設備。
有解決方法,但沒有通用的。 您必須更詳細地解釋Device
的用途、 T
代表什么、 update
應該做什么、您的系統如何工作等等。
盡管如此,如果您要使用此設置轉到 go,其中不可避免地會出現帶有警告的強制轉換,至少將錯誤放在正確的位置,這不是通過破壞update()
的簽名,因為這是一個方法簽名. 這些很重要。
相反,然后在呼叫站點“修復”它。 在這里,這意味着將device
(局部變量)設為a raw type (just
Device` - 是的,這會給你一個警告,這就是重點:如果不重寫不使用異構映射,就無法避免它)。 這樣,generics 問題至少不會出現在方法簽名中。
如果我們不能消除“unchecked cast”警告並且我們確定引發警告的代碼是類型安全的,我們可以使用 SuppressWarnings(“unchecked”) 注釋來抑制警告。
@Getter
@Setter
public class Device<T> {
private boolean updated;
private T value;
private Date updatedAt;
public void update(Device<?> p) {
SuppressWarnings(“unchecked”)
this.value = (T) p.getValue(); // unchecked case warning
this.updatedAt = p.getUpdatedAt();
this.updated = true;
}
}
編譯器必須允許此轉換以保持與不支持 generics 的舊 Java 版本的向后兼容性。 在我們加載錯誤類型的數據之前,不會拋出 ClassCastException。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.