簡體   English   中英

如何使用 Java Generic 來抑制警告?

[英]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.

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