/ / Безопасност на типа: Непроверен отлив - java, пружина, тип-безопасност, непроверен

Безопасност на типа: Непроверен отлив - java, пружина, тип-безопасност, непроверен

В контекста на пролетното ми приложение имам нещо като:

<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 виждам предупреждение, което казва:

Безопасност на типа: Непроверено подаване от Object на HashMap

Какво съм направил погрешно? Как да разреша проблема?

Отговори:

218 за отговор № 1

Първо, вие губите памет с новото HashMap създаване на повикване. Втората ви линия напълно пренебрегва позоваването на тази създадена hashmap, което я прави достъпна за боклука. Така че, не го правете, използвайте:

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

Второ, компилаторът се оплаква, че сте хвърлили обекта в a 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> ако обичаш. По този начин, няма гаранция, че когато получите своя боб, той може да бъде представен като HashMap<String, String> защото можеше да имаш HashMap<Date, Calendar> защото негенеричното представяне, което се връща, може да има някакви обекти.

Ако кодът се компилира и можете да го изпълните String value = map.get("thisString"); без никакви грешки, не се притеснявайте за това предупреждение. Но ако картата не е изцяло от низови ключове за низови стойности, ще получите ClassCastException по време на изпълнение, защото генеричните лекарства не могат да блокират това да се случи в този случай.


263 за отговор № 2

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

употреба @SuppressWarnings("unchecked") и задръж носа си. О, и кампания за утвърдени генерични продукти в Java :)


59 за отговор № 3

Както показват горните съобщения, списъкът не може да бъде различен между a List<Object> и a 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);

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


22 за отговор № 4

Точно това е предупреждение. Предупреждение. Понякога предупрежденията са без значение, понякога те не са. Те са свикнали да привличат вниманието ви към нещо, което компилаторът смята за проблем, но може и да не е така.

В случай на хвърляне, той винаги ще дадепредупреждение в този случай. Ако сте абсолютно сигурни, че даден акцент ще бъде безопасен, тогава трябва да помислите за добавяне на бележка като тази (не съм сигурен за синтаксиса) точно преди реда:

@SuppressWarnings (value="unchecked")

9 за отговор № 5

Получавате това съобщение, защото getBeanвръща референция на обект и я препращате към правилния тип. Java 1.5 ви дава предупреждение. Това е естеството на използването на Java 1.5 или по-добре с код, който работи по този начин. Пролетта има typeafe версията

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

в списъка си със задачи.


5 за отговор № 6

Ако наистина искате да се отървете от предупрежденията, едно нещо, което можете да направите, е да създадете клас, който се простира от общия клас.

Например, ако се опитвате да използвате

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

Можете да създадете нов клас като такъв

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

Тогава, когато използвате

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

Компилаторът не знае какво (не е повечегенерични), и няма да има предупреждение. Това може би не винаги е идеалното решение, някои може да се аргументират с този вид загуба на целта на общите класове, но вие все още използвате повторно целия код от общия клас, просто декларирате при компилация какъв тип искате да използвате.


1 за отговор № 7

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

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

0 за отговор № 8

Под кода причинява безопасност за тип Предупреждение

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

Временно решение

Създайте нов обект на Map без да споменавате параметрите, защото типът на обекта, който се съхранява в списъка, не е проверен.

Етап 1: Създайте нова временна карта

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

Стъпка 2: Задействайте основната карта

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

Стъпка 3: Проверете временната карта и задайте стойностите в основната карта

 for(Map.Entry<?, ?> entry :myInputObj.entrySet()){
myInput.put((String)entry.getKey(),entry.getValue());
}