Zabezpieczenie typu: odlew nieobrobiony
W moim pliku kontekstowym aplikacji wiosennej mam coś takiego:
<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>
W klasie java implementacja wygląda następująco:
private Map<String, String> someMap = new HashMap<String, String>();
someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
W Eclipse, widzę Ostrzeżenie, które mówi:
Type safety: Unchecked cast from Object to HashMap
Co zrobiłem źle? Jak mogę rozwiązać problem?9 answers
Po pierwsze, marnujesz pamięć z nowym wywołaniem tworzenia. Druga linia całkowicie pomija odniesienie do tej utworzonej hashmapy, czyniąc ją dostępną dla garbage collector. Więc nie rób tego, użyj:
private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
Po Drugie, kompilator skarży się, że oddajesz obiekt HashMap
bez sprawdzania, czy jest to HashMap
. Ale nawet gdybyś miał zrobić:
if(getApplicationContext().getBean("someMap") instanceof HashMap) {
private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
}
Prawdopodobnie nadal otrzymałbyś to Ostrzeżenie. Problem w tym, że getBean
zwraca Object
, więc nie wiadomo, jaki jest typ. Konwersja do HashMap
bezpośrednio nie spowodowałaby problemu w drugim przypadku (i być może nie byłoby ostrzeżenia w pierwszym przypadku, nie jestem pewien, jak pedantyczny jest kompilator Javy z ostrzeżeniami dla Javy 5). Jednak konwertujesz go na HashMap<String, String>
.
Hashmapy są tak naprawdę mapami, które przyjmują obiekt jako klucz i mają obiekt jako wartość, HashMap<Object, Object>
jeśli wolisz. W związku z tym nie ma gwarancji, że po otrzymaniu fasoli można ją przedstawić jako HashMap<String, String>
ponieważ możesz mieć HashMap<Date, Calendar>
ponieważ nie-ogólna reprezentacja, która jest zwracana, może mieć dowolne obiekty.
Jeśli kod zostanie skompilowany i możesz wykonać String value = map.get("thisString");
bez żadnych błędów, nie martw się tym ostrzeżeniem. Jeśli jednak mapa nie zawiera całkowicie kluczy łańcuchowych do wartości łańcuchowych, otrzymasz ClassCastException
w czasie wykonywania, ponieważ generyki nie mogą tego zablokować.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-07 12:55:44
Problem polega na tym, że cast jest sprawdzaniem czasu pracy - ale ze względu na typ erasure, w czasie pracy nie ma żadnej różnicy między HashMap<String,String>
i HashMap<Foo,Bar>
dla innych Foo
i Bar
.
Użyj @SuppressWarnings("unchecked")
i trzymaj nos. AHA, i kampania dla reified generics w Javie:)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-04 17:09:19
Jak wskazują powyższe wiadomości, listy nie można rozróżnić między A List<Object>
i a List<String>
lub List<Integer>
.
Rozwiązałem ten Komunikat o błędzie dla podobnego problemu:
List<String> strList = (List<String>) someFunction();
String s = strList.get(0);
Z następującym:
List<?> strList = (List<?>) someFunction();
String s = (String) strList.get(0);
Wyjaśnienie: pierwsza konwersja typu sprawdza, czy obiekt jest listą bez dbania o typy wewnątrz (ponieważ nie możemy zweryfikować typów wewnętrznych na poziomie listy). Druga konwersja jest teraz wymagana, ponieważ kompilator zna tylko listę zawiera jakieś przedmioty. To sprawdza typ każdego obiektu na liście, gdy jest dostępny.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-02 10:05:02
Tylko Ostrzeżenie. Ostrzeżenie. Czasami ostrzeżenia są nieistotne, czasami nie. Są one używane, aby zwrócić twoją uwagę na coś, co kompilator myśli, że może być problemem, ale może nie być.
/Align = "left" / Jeśli jesteś absolutnie pewien, że Dana Obsada będzie bezpieczna, powinieneś rozważyć dodanie adnotacji w ten sposób (nie jestem pewien składni) tuż przed wierszem:@SuppressWarnings (value="unchecked")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-04 16:44:24
Otrzymujesz tę wiadomość, ponieważ getBean zwraca odniesienie do obiektu i przerzucasz je na właściwy typ. Java 1.5 daje ostrzeżenie. Taka jest natura używania Javy 1.5 lub lepszej z kodem, który działa w ten sposób. Wiosna ma wersję typesafe
someMap=getApplicationContext().getBean<HashMap<String, String>>("someMap");
Na jego liście todo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-04 16:44:59
Jeśli naprawdę chcesz pozbyć się ostrzeżeń, możesz utworzyć klasę, która rozciąga się od klasy generycznej.
Na przykład, jeśli próbujesz użyć
private Map<String, String> someMap = new HashMap<String, String>();
Możesz utworzyć nową klasę w taki sposób
public class StringMap extends HashMap<String, String>()
{
// Override constructors
}
Wtedy gdy używasz
someMap = (StringMap) getApplicationContext().getBean("someMap");
Kompilator wie, czym są (już nie ogólne) typy i nie będzie żadnego ostrzeżenia. Może to nie zawsze być idealne rozwiązanie, niektórzy mogą argumentować, że tego rodzaju klasy generyczne nie spełniają celu, ale nadal używasz tego samego kodu z klasy generic, po prostu deklarujesz w czasie kompilacji, jakiego typu chcesz użyć.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-13 15:55:31
Innym rozwiązaniem, jeśli często rzucasz ten sam obiekt i nie chcesz zaśmiecać kodu @SupressWarnings("unchecked")
, byłoby stworzenie metody z adnotacją. W ten sposób centralizujesz obsadę i mam nadzieję, że zmniejszysz prawdopodobieństwo błędu.
@SuppressWarnings("unchecked")
public static List<String> getFooStrings(Map<String, List<String>> ctx) {
return (List<String>) ctx.get("foos");
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-20 19:25:17
Poniższy kod powoduje Typ Ostrzeżenia bezpieczeństwa
Map<String, Object> myInput = (Map<String, Object>) myRequest.get();
Obejście
Utwórz nowy obiekt mapy bez podawania parametrów, ponieważ typ obiektu przechowywanego na liście nie jest zweryfikowany.
Krok 1: Tworzenie nowej tymczasowej mapy
Map<?, ?> tempMap = (Map<?, ?>) myRequest.get();
Krok 2: Instantiate the main Map
Map<String, Object> myInput=new HashMap<>(myInputObj.size());
Krok 3: iteracja tymczasowej Mapy i ustawienie wartości do głównej mapy
for(Map.Entry<?, ?> entry :myInputObj.entrySet()){
myInput.put((String)entry.getKey(),entry.getValue());
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-16 14:23:25
Rozwiązanie, aby uniknąć niezaznaczonego Ostrzeżenia:
class MyMap extends HashMap<String, String> {};
someMap = (MyMap)getApplicationContext().getBean("someMap");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-28 15:50:10