2008-11-04 4 views
185

В моем весеннем контексте файла приложения, у меня есть что-то вроде:Тип безопасности: Переполнение отливать

<util:map id="someMap" map-class="java.util.HashMap" key-type="java.lang.String" value-type="java.lang.String"> 
    <entry key="some_key" value="some value" /> 
    <entry key="some_key_2" value="some value" /> 
</util:map> 

В классе Java, реализация выглядит следующим образом:

private Map<String, String> someMap = new HashMap<String, String>(); 
someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap"); 

В Eclipse, я вижу предупреждение что говорит:

Тип безопасности: Переполнение отлиты из объекта в HashMap

Что я сделал не так? Как решить проблему?

+0

Родственных/простофилей: [Как я обращаюсь непроверенные предупреждения актеров?] (Http://stackoverflow.com/q/509076) – blahdiblah 2013-03-11 19:15:18

+0

возможного дубликата из [Как удалить непроверенные предупреждения о броске?] (http://stackoverflow.com/questions/509076/how-do-i-address-unchecked-cast-warnings) – 2014-08-19 11:16:24

+0

Я придумал рутину, чтобы на самом деле проверить личность для параметризованного HashMap, который устраняет предупреждение без предупреждения: [link] (http://stackoverflow.com/questions/509076/how-do-i-address-unchecked-cast-warnings/509230#509230) Я бы сказал, это это «правильное» решение, но может ли оно быть спорным. :) – skiphoppy 2009-02-04 17:27:22

ответ

211

Ну, во-первых, вы тратите память на новый вызов создания HashMap. Ваша вторая строка полностью игнорирует ссылку на этот созданный хэш, что делает ее доступной сборщику мусора. Таким образом, не делают этого, использование:

private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap"); 

Во-вторых, компилятор жалуется, что вы приводите объект к HashMap без проверки, если это HashMap. Но, даже если вы должны были сделать:

if(getApplicationContext().getBean("someMap") instanceof HashMap) { 
    private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap"); 
} 

Возможно, вы все равно получите это предупреждение. Проблема в том, что getBean возвращает Object, поэтому неизвестно, что это за тип. Преобразование его в HashMap напрямую не вызовет проблемы со вторым случаем (и, возможно, в первом случае не было бы предупреждения, я не уверен, насколько педантичен компилятор Java с предупреждениями для Java 5). Однако вы конвертируете его в HashMap<String, String>.

HashMaps - это действительно карты, которые берут объект в качестве ключа и имеют объект как значение, HashMap<Object, Object>, если хотите. Таким образом, нет никакой гарантии, что когда вы получите свой bean-компонент, он может быть представлен как HashMap<String, String>, потому что у вас может быть HashMap<Date, Calendar>, потому что не общее представление, которое возвращается, может иметь любые объекты.

Если код скомпилирован, и вы можете выполнить String value = map.get("thisString"); без каких-либо ошибок, не беспокойтесь об этом предупреждении. Но если карта не полностью содержит строковые ключи для строковых значений, вы получите ClassCastException во время выполнения, потому что генерики не могут заблокировать это в этом случае.

+10

Это было некоторое время назад, но я искал ответ на проверку типа Set перед актом, и вы не можете instanceof на параметризованном родовом значении. например if (event.getTarget instanceof Set ). Вы можете ввести только тип проверки с помощью? и это не приведет к удалению предупреждения о броске. например if (event.getTarget instanceof Set ) – garlicman 2012-02-14 15:56:08

21

Предупреждение именно это. Предупреждение. Иногда предупреждения не имеют значения, иногда это не так. Они используются, чтобы привлечь ваше внимание к тому, что, по мнению компилятора, может быть проблемой, но может и не быть.

В случае бросков он всегда будет давать предупреждение в этом случае. Если вы абсолютно уверены в том, что конкретный бросок будет безопасным, то вам следует рассмотреть возможность добавления аннотаций, как это (я не уверен, синтаксис) непосредственно перед линией:

@SuppressWarnings (value="unchecked") 
+8

-1: предупреждение никогда не должно приниматься. Или подавите эти предупреждения или исправьте это. Наступит момент, когда вы будете иметь много предупреждений, и вы не увидите соответствующий один раз. – ezdazuzena 2013-10-16 09:58:21

9

Вы получаете это сообщение, потому что getBean возвращает ссылку Object, и вы переводите ее в правильный тип. Java 1.5 дает вам предупреждение. Это характер использования Java 1.5 или лучше с кодом, который работает так. Весна имеет типовое исполнение

someMap=getApplicationContext().getBean<HashMap<String, String>>("someMap"); 

в своем списке задач.

248

Проблема заключается в том, что отливка является проверка выполнения - но из-за типа стирания, во время выполнения нет фактически никакой разницы между HashMap<String,String> и HashMap<Foo,Bar> для любого другого Foo и Bar.

Используйте @SuppressWarnings("unchecked") и держите нос. О, и кампания реифицированными генериков в Java :)

53

Как сообщения выше указания, список не может быть дифференцированы между List<Object> и List<String> или List<Integer>.

Я решил это сообщение об ошибке для аналогичной задачи:

List<String> strList = (List<String>) someFunction(); 
String s = strList.get(0); 

со следующим:

List<?> strList = (List<?>) someFunction(); 
String s = (String) strList.get(0); 

Объяснение: Первое преобразование типа проверяет, что объект списка, не заботясь о типы, хранящиеся внутри (поскольку мы не можем проверить внутренние типы на уровне списка). Второе преобразование теперь требуется, потому что компилятор знает, что List содержит какие-то объекты. Это проверяет тип каждого объекта в Списке по мере его доступа.

4

Если вы действительно хотите избавиться от предупреждений, вы можете создать класс, который простирается от общего класса.

Например, если вы пытаетесь использовать

private Map<String, String> someMap = new HashMap<String, String>(); 

Вы можете создать новый класс как такой

public class StringMap extends HashMap<String, String>() 
{ 
    // Override constructors 
} 

Затем, когда вы используете

someMap = (StringMap) getApplicationContext().getBean("someMap"); 

Компилятор ДЕЛАЕТ знайте, какие (более не общие) типы, и не будет никаких предупреждений. Это не всегда может быть идеальным решением, некоторые могут утверждать, что этот вид поражений предназначен для универсальных классов, но вы все еще повторно используете все одинаковые коды из общего класса, вы просто объявляете во время компиляции, какой тип вы хотите использовать.

1

Другое решение, если вы обнаруживаете, что вы очень много ливаете один и тот же объект, и вы не хотите, чтобы ваш код был помечен @SupressWarnings("unchecked"), было бы создать метод с аннотацией. Таким образом, вы централизуете актерский состав и, надеюсь, уменьшаете вероятность ошибки.

@SuppressWarnings("unchecked") 
public static List<String> getFooStrings(Map<String, List<String>> ctx) { 
    return (List<String>) ctx.get("foos"); 
} 
0

Ниже код причины типа по технике безопасности Предупреждение

Map<String, Object> myInput = (Map<String, Object>) myRequest.get();

Обход

Создать новую карту объекта без указания параметров, так как тип объекта проведен в списке есть n Проверено.

Шаг 1: Создать новую временную карту

Map<?, ?> tempMap = (Map<?, ?>) myRequest.get();

Шаг 2: Instantiate главная Карта

Map<String, Object> myInput=new HashMap<>(myInputObj.size()); 

Шаг 3: Iterate временная карта и установите значения в основную карту

for(Map.Entry<?, ?> entry :myInputObj.entrySet()){ 
     myInput.put((String)entry.getKey(),entry.getValue()); 
    } 
Смежные вопросы