În primăvara aplicarea context fișier, am ceva de genul:
<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>
În clasa java, implementarea arata ca:
private Map<String, String> someMap = new HashMap<String, String>();
someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
În Eclipsa, am vedea un avertisment care spune:
Tip siguranta: Necontrolata a aruncat de la Obiect la HashMap<String,String>
Ce am făcut greșit? Cum pot rezolva problema?
Problema este că o distribuție este un runtime check - dar datorită tip ștergerea, la runtime nu's, de fapt, nici o diferență între un HashMap<String,String> " și "HashMap<Foo,Bar> pentru orice alte" Foo " și "Bar".
Utilizarea `@SuppressWarnings("necontrolat") și țineți-vă de nas. Oh, și campania pentru reificate generice în Java :)
Ei bine, mai întâi de toate,'re a pierde memoria cu HashMap crearea de apel. A doua linie ignoră complet de referință pentru acest lucru a creat hashmap, făcându-l disponibil pentru colectorul de gunoi. Deci, don't de a face asta:
private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
În al doilea rând, compilatorul este proteste care i-ai făcut obiectul unei HashMap
fără a verifica dacă este un HashMap`. Dar, chiar dacă ai de-a face:
if(getApplicationContext().getBean("someMap") instanceof HashMap) {
private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
}
Te-ar mai primi acest avertisment. Problema este, getBean
întoarce "Obiect", deci nu se știe ce tip este. Conversia la HashMap
direct nu ar cauza problema cu cel de-al doilea caz (și, probabil, nu ar fi un avertisment în primul caz, am'm nu sunt sigur cum pedant Java compiler este cu avertismente pentru Java 5). Cu toate acestea, sunt de conversie de la un HashMap<String, String>`.
HashMaps sunt de fapt hărți care lua un obiect ca o cheie și au un obiect ca o valoare, HashMap<Obiect, Obiect>
dacă vrei. Astfel, nu există nici o garanție că atunci când vei ajunge de fasole, care poate fi reprezentat ca un HashMap<String, String> pentru ca ai putea avea HashMap<Data, Calendar> pentru non-generic reprezentare care este returnat poate avea orice obiecte.
Dacă codul compileaza, și puteți executa String value = hartă.ia("thisString");
fără erori, don't vă faceți griji despre acest avertisment. Dar dacă harta e't complet de șir cheile de la șirul de valori, vei primi un ClassCastException la runtime, pentru că medicamentele generice nu poate bloca acest lucru să se întâmple în acest caz.
Ca mesajele de mai sus indica, Lista nu pot fi diferențiate între o Listă
Am'am rezolvat acest mesaj de eroare de o problema asemanatoare:
List<String> strList = (List<String>) someFunction();
String s = strList.get(0);
cu următorul text:
List<?> strList = (List<?>) someFunction();
String s = (String) strList.get(0);
Explicație: primul tip de conversie verifică dacă obiectul este o Listă fără să le pese de tipuri loc în termen de (deoarece nu putem verifica interne tipuri la nivelul Lista). Cea de-a doua conversie este acum necesar deoarece compilatorul știe doar Lista conține un fel de obiecte. Aceasta verifică tipul de fiecare obiect din Listă este accesat.
Un avertisment este doar faptul că. Un avertisment. Uneori avertismente sunt irelevante, uneori, ei're nu. Ei're folosit pentru a apela atenția la ceva care compilatorul crede că ar putea fi o problemă, dar nu poate fi.
În caz de mulaje, l's întotdeauna de gând să dea un avertisment în acest caz. Dacă sunteți absolut sigur că o anumită distribuție va fi în siguranță, atunci ar trebui să ia în considerare adăugarea o adnotare de genul asta (m-am'm nu sunt sigur de sintaxa) înainte de linia:
@SuppressWarnings (value="unchecked")
Primiți acest mesaj deoarece getBean returnează un Obiect de referință și se casting pentru tipul corect. Java 1.5-ți dă un avertisment. Ca's naturii folosind Java 1.5 sau mai bine cu cod care funcționează ca aceasta. Primăvara are typesafe versiune
someMap=getApplicationContext().getBean<HashMap<String, String>>("someMap");
pe lista de todo.
Dacă vrei cu adevărat să scapi de avertismente, un lucru care le puteți face este de a crea o clasă care se extinde de la clasă generică.
De exemplu, dacă're încercarea de a utiliza
private Map<String, String> someMap = new HashMap<String, String>();
Puteți crea o nouă clasă ca și cum ar
public class StringMap extends HashMap<String, String>()
{
// Override constructors
}
Atunci când utilizați
someMap = (StringMap) getApplicationContext().getBean("someMap");
Compilatorul NU stiu ce (nu mai generic) tipuri sunt, și nu va fi nici o avertizare. Acest lucru nu poate fi întotdeauna soluția perfectă, unii ar putea argumenta că acest fel de a învinge în scopul de generic clase, dar're încă re-folosind toate același cod de clasă generică, ai're doar declararea la compilare ce tip doriți să o utilizați.
O altă soluție, dacă vă aflați turnare același obiect o mulțime și nu't doriți să așternut, codul cu @SupressWarnings("necontrolat")
, ar fi de a crea o metodă cu adnotarea. În acest fel te're centralizarea exprimate, și, sperăm, reducând posibilitatea de eroare.
@SuppressWarnings("unchecked")
public static List<String> getFooStrings(Map<String, List<String>> ctx) {
return (List<String>) ctx.get("foos");
}
Mai jos codul de cauze Tip de siguranță Avertisment
Harta<String, Obiect> myInput = (Harta<String, Obiect>) myRequest.get();
Soluție
A crea o nouă Hartă a Obiectelor fără a menționa parametrii pentru tipul de obiect a avut loc în listă nu este verificată.
Pasul 1: Crearea unei noi temporară Hartă
Harta<?, ?> tempMap = (Harta<?, ?>) myRequest.get();
Pasul 2: Instantia principalele Hartă
Map<String, Object> myInput=new HashMap<>(myInputObj.size());
Pasul 3: Itera temporară Hartă și setați valorile în principal Hartă
for(Map.Entry<?, ?> entry :myInputObj.entrySet()){
myInput.put((String)entry.getKey(),entry.getValue());
}
Ce am făcut greșit? Cum pot rezolva problema?
Aici :
Harta<String,String> someMap = (Harta<String,String>)getApplicationContext().getBean("someMap");
Utilizați o metoda de moștenire pe care noi, în general, nu't doriți să utilizați din care returnează "Obiect":
Object getBean(String name) throws BeansException;
Metoda de serviciu pentru a obține (pentru singleton) / crea (de prototip) o boaba de fasole din fabrică este :
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Folosind-o, cum ar fi :
Map<String,String> someMap = app.getBean(Map.class,"someMap");
va compila, dar încă cu o necontrolate de avertizare de conversie de toate "Harta" obiecte nu sunt neapărat Harta<String, String>` obiecte.
Dar <T> T getBean(String nume, Clasa<T> requiredType) aruncă BeansException;
nu este suficient în fasole generic clase, cum ar fi generic colecții din care necesită pentru a specifica mai mult de o clasă ca parametru : tipul de colectare și de tip generic(e).
În acest tip de scenariu și, în general, o mai bună abordare este de a nu folosi direct BeanFactory
metode dar lasa-cadru pentru a injecta bean.
Bean-ul declarație :
@Configuration
public class MyConfiguration{
@Bean
public Map<String, String> someMap() {
Map<String, String> someMap = new HashMap();
someMap.put("some_key", "some value");
someMap.put("some_key_2", "some value");
return someMap;
}
}
Fasole injecție :
@Autowired
@Qualifier("someMap")
Map<String, String> someMap;