簡體   English   中英

在Java中強制轉換為泛型類時鍵入安全警告

[英]Type Safety warning when casting to generic class in Java

我有一堂課

class Property<T> {
    value T;

    public void setValue(T value) {
        this.value = value;
    }
}

現在,我有了一個列表List<Property<?>> properties其中包含各種類型的各種屬性。 我遍歷此列表,並希望設置每個屬性的值。 因此,我需要將通用屬性轉換為正確的類型,例如:對於Integer:

if (property.getType().equals("Integer")) {
        Property<Integer> propInt = (Property<Integer>) property;
        propInt.setValue((Integer) values[i++]);
}

其中values[]是一個對象數組,其中包含我要設置的值。

一切正常,但是Java抱怨類型安全“未經檢查從Property<?>Property<Integer> ”。 像這樣的支票

if (property instanceof Property<Integer>){...}

雖然不可能。 我該如何更改代碼以消除此警告,或者您知道我的案例的更好做法?

編譯器抱怨是因為property的類型為Property<?> ,通常它可能是也不可能是Property<Integer>類型。 由於類型擦除,這是當前Java語言的固有限制。

在這種特殊情況下,您可以通過使用getType方法來確保該property屬於Property<Integer>類,因此可以安全地忽略該警告。

if (property.getType().equals("Integer")) {
        // we have made sure property is of class Property<Integer> so the cast is type safe
        @SuppressWarnings("unchecked")
        Property<Integer> propInt = (Property<Integer>) property;
        propInt.setValue((Integer) values[i++]);
}

重要的是要用注釋記錄下來,否則查看您的代碼的同行可能不會注意到確實類型轉換是安全的,並且可能將警告抑制作為不當行為加以混淆。

警告表明,在源級別,列表可能包含任何類型()的對象,並且將它們強制轉換為Integer,如果列表包含非Integer對象,則在運行時會導致ClassCastException。 因此,警告表明在運行時存在潛在問題。

您可以通過以下兩種方法擺脫警告

  • 將列表聲明為整數List<Integer>
  • 或者,使用方法或列表聲明中的@SuppressWarnings("unchecked")警告。

如果不能保證列表中包含的對象不是Integer,則在轉換和SuppressWarning之前應該具有instanceof 如果可以保證,則應將該列表聲明為Integers列表。

您可以使用annotation SuppressWarnings忽略此警告:

@SuppressWarnings("unchecked") Property<Integer> propInt = (Property<Integer>) property;

但是這樣做是有風險的。

此警告是由於類型擦除引起的,因為在編譯時, 泛型將被擦除。

如您所知,java中的泛型會遭受類型擦除,所有這些在運行時都變為Object。

當您對“ Integer”之Class<T>字符串進行測試時,添加Class<T>似乎更為方便。

class Property<T> {
    final Class<T> type;
    value T;

    public Property(Class<T> type) {
        this.type = type;
    }

    public void setAnyValue(Object value) {
        this.value = type.cast(value);
    }
}

Property<?> property = ...
//if (property.getType() == Integer.class) {
//    Property<Integer> propInt = (Property<Integer>) property;
//    propInt.setAnyValue((Integer) values[i++]);
//}
property.setAnyValue(values[i++]);

Object的使用歸因於Property的多態使用,而不是更普通的鍵入:您的代碼混合了不同類型的屬性和並行值。

如果您正在使用spring框架,則還可以使用:

import static org.springframework.data.util.CastUtils.cast;
        Map<String,Object> messageMap = cast(exchange.getMessage().getBody());
        List<String> refIds = cast(messageMap.get("refIds"));

注意:

除非spring框架已成為您應用程序的一部分,否則我不建議您使用此功能。

暫無
暫無

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

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