Kaip elgtis su nepatvirtintais įspėjimais?

„Eclipse“ įspėja apie šią formą:

Apsaugos tipas: nušautas iš objekto „HashMap“

Tai yra API skambutis, kuriam aš negaliu kontroliuoti objekto grąžinimo:

 HashMap<String, String> getItems(javax.servlet.http.HttpSession session) { HashMap<String, String> theHash = (HashMap<String, String>)session.getAttribute("attributeKey"); return theHash; } 

Norėčiau išvengti „Eclipse“ įspėjimų, jei tai įmanoma, nes teoriškai jie nurodo bent galimą kodo problemą. Tačiau dar nepavyko rasti gero būdo išspręsti šią problemą. Aš galiu išskleisti pačią eilutę, susijusią su šiuo metodu, ir pridėti prie šio metodo @SuppressWarnings("unchecked") , taip apribojant kodo bloko poveikį, kai @SuppressWarnings("unchecked") įspėjimų. Ar yra geresnių variantų? Nenoriu išjungti šių įspėjimų „Eclipse“.

Prieš atėjęs prie kodo, jis buvo paprastesnis, bet vis tiek sukėlė įspėjimus:

 HashMap getItems(javax.servlet.http.HttpSession session) { HashMap theHash = (HashMap)session.getAttribute("attributeKey"); return theHash; } 

Problema buvo kitur, kai bandėte naudoti „hash“, kurį gausite įspėjimus:

 HashMap items = getItems(session); items.put("this", "that"); Type safety: The method put(Object, Object) belongs to the raw type HashMap. References to generic type HashMap<K,V> should be parameterized. 
452
04 февр. skiphoppy set 04 Feb 2009-02-04 00:57 '09 ne 0:57 2009-02-04 00:57
@ 24 atsakymai

Oho; Manau, kad suprantu atsakymą į mano klausimą. Aš nesu tikras, kad verta! :)

Problema ta, kad dauguma nėra patikrinta. Taigi turėtumėte tai patikrinti. Jūs negalite paprasčiausiai patikrinti parametrų tipo su instancija, nes informacija apie parametruotą tipą neveikia vykdymo metu, ištrinama kompiliavimo metu.

Bet jūs galite patikrinti kiekvieną maišos elementą, naudodami instanciją, ir jūs galite sukurti naują saugą pagal tipą. Ir jūs nesukelsite jokių įspėjimų.

Ačiū mmyers ir Esko Luontola, aš parametruoju kodą, kurį aš iš pradžių čia parašiau, todėl jis gali būti užpildytas kažkur naudingumo klasėje ir naudojamas bet kuriam parametruojamam HashMap. Jei norite geriau jį suprasti ir nežino bendrųjų vaistų, rekomenduoju peržiūrėti šio atsakymo pasikeitimo istoriją.

 public static <K, V> HashMap<K, V> castHash(HashMap input, Class<K> keyClass, Class<V> valueClass) { HashMap<K, V> output = new HashMap<K, V>(); if (input == null) return output; for (Object key: input.keySet().toArray()) { if ((key == null) || (keyClass.isAssignableFrom(key.getClass()))) { Object value = input.get(key); if ((value == null) || (valueClass.isAssignableFrom(value.getClass()))) { K k = keyClass.cast(key); V v = valueClass.cast(value); output.put(k, v); } else { throw new AssertionError( "Cannot cast to HashMap<"+ keyClass.getSimpleName() +", "+ valueClass.getSimpleName() +">" +", value "+ value +" is not a "+ valueClass.getSimpleName() ); } } else { throw new AssertionError( "Cannot cast to HashMap<"+ keyClass.getSimpleName() +", "+ valueClass.getSimpleName() +">" +", key "+ key +" is not a " + keyClass.getSimpleName() ); } } return output; } 

Tai daug darbo, galbūt labai nedideliam atlygiui ... nesu įsitikinęs, ar naudosiu, ar ne. Norėčiau dėkoti už komentarus, ar žmonės mano, kad tai vertas, ar ne. Be to, norėčiau padėkoti kai kuriems patobulinimų pasiūlymams: ar yra kažkas geresnio, ką galėčiau padaryti ne tik pareikalavęs? Ar galiu kažką geriau atsisakyti? Ar turėčiau tai padaryti įrodyta išimtis?

108
04 февр. Atsakymas pateikiamas skiphoppy 04 Feb. 2009-02-04 01:35 '09 ne 1:35 2009-02-04 01:35

Akivaizdus atsakymas, žinoma, nėra nevaldomas aktorius.

Jei tai yra absoliučiai būtina, bent jau pabandykite apriboti @SuppressWarnings anotacijos sritį. Pasak jo „ Javadocs“ , jis gali pereiti prie vietinių kintamųjų; todėl jis netgi neturi įtakos visam metodui.

Pavyzdys:

 @SuppressWarnings("unchecked") Map<String, String> myMap = (Map<String, String>) deserializeMap(); 

Negalima nustatyti, ar Map turi būti bendri parametrai <String, String> . Turite iš anksto žinoti, kokius parametrus turėtumėte turėti (arba žinosite, kada gausite ClassCastException ). Štai kodėl kodas sukuria įspėjimą, nes kompiliatorius negali žinoti, ar jis yra saugus.

416
04 февр. Michael Myers atsakymas, pateiktas vasario 04 d 2009-02-04 01:07 '09, 1:07 2009-02-04 01:07

Deja, nėra puikių galimybių. Nepamirškite, kad visa tai yra saugoti. „ Java Generics “ siūlo sprendimus, kaip dirbti su ne bendromis pasenusiomis bibliotekomis, ir ypač tai vadinama „tuščios kilpos metodu“ 8.2 skyriuje. Iš esmės, nesaugiai išmeskite ir slopinkite įspėjimą. Tada slinkite žemėlapį taip:

 @SuppressWarnings("unchecked") Map<String, Number> map = getMap(); for (String s : map.keySet()); for (Number n : map.values()); 

Jei aptinkamas netikėtas tipas, vykdymo metu gausite ClassCastException išimtį, tačiau bent jau jis bus artimas problemos šaltiniui.

108
04 февр. Atsakymas pateikiamas Julien Chastang 04 vasaris. 2009-02-04 01:46 '09 ne 1:46 2009-02-04 01:46

„Eclipse“ nustatymuose eikite į Java-> Compiler-> Klaidos / Įspėjimai-> Bendrųjų tipų ir patikrinkite >Ignore unavoidable generic type problems .

Tai atitinka klausimo problemą, t. Y.

Norėčiau išvengti „Eclipse“ įspėjimų ...

jei ne dvasia.

47
21 окт. Atsakyti Dave 21 okt. 2011-10-21 20:40 '11 prie 20:40 2011-10-21 20:40

Galite sukurti naudingumo klasę taip ir naudokite ją nepatvirtintam įspėjimui slopinti.

 public class Objects {  @SuppressWarnings({"unchecked"}) public static <T> T uncheckedCast(Object obj) { return (T) obj; } } 

Ją galite naudoti taip:

 import static Objects.uncheckedCast; ... HashMap<String, String> getItems(javax.servlet.http.HttpSession session) { return uncheckedCast(session.getAttribute("attributeKey")); } 

Daugiau apie tai skaitykite šiuo adresu: http://clenteenias.blogs.com/thought_spearmints/2006/01/suppresswarning.html

19
04 февр. atsakymą pateikė Esko Luontola 04 vasaris. 2009-02-04 01:54 '09 ne 1:54 2009-02-04 01:54

Tai sunku, bet čia yra mano dabartinės mintys:

Jei jūsų API grąžina objektą, tuomet jūs negalite nieko daryti - nepriklausomai nuo to, ar aklai mesti akį. Galite leisti „Java“ skambinti „ClassCastExceptions“, arba galite patikrinti kiekvieną elementą patys, taip pat skambinti teiginiais arba „IllegalArgumentExceptions“ arba kai kuriais iš jų, tačiau šie patikrinimai yra lygiaverčiai. Jūs turite slopinti nekontroliuojamo kompiliacijos laiką, nepriklausomai nuo to, ką darote vykdymo metu.

Aš tiesiog norėčiau, kad aklas mesti, ir leiskite JVM atlikti man patikros patikrinimą, nes mes „žinome“, ką API turėtų sugrįžti, ir paprastai nori daryti prielaidą, kad API veikia. Jei jums jų reikia, naudokite generinius vaistus. Jūs iš tikrųjų nieko neperkate, nes jūs vis dar turite vienišas aklumas, bet bent jau galite naudoti generinius vaistus, kad JVM galėtų padėti išvengti aklųjų bangos kitų kodo dalių.

Šiuo konkrečiu atveju, matyt, galite matyti skambutį SetAttribute ir pamatyti, kad tipas ateina, todėl tiesiog aklai atmesti tipą taip pat nėra amoralus išvestyje. Pridėti komentarą „SetAttribute“ ir padarykite jį su juo.

17
02 марта '11 в 2:04 2011-03-02 02:04 atsakymą pateikė Dustin Getz kovo 2 d. 11 d. 2 val. 2011-03-02 02:04

HTTP sesijų pasaulyje iš tikrųjų negalite pabėgti, nes API yra parašyta tokiu būdu (ji priima ir grąžina tik Object ).

Su ClassCastException galite lengvai išvengti neišbandytos metimo. “Tai reiškia, kad jis taps tradiciniu metimu, suteikdamas ClassCastException teisę, jei bus padaryta klaida.) Nekontroliuojama išimtis gali bet kada vėliau paversti CCE kuris yra atskiras įspėjimas).

Pakeisti „HashMap“ specialią klasę:

 import java.util.AbstractMap; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; public class Attributes extends AbstractMap<String, String> { final Map<String, String> content = new HashMap<String, String>(); @Override public Set<Map.Entry<String, String>> entrySet() { return content.entrySet(); } @Override public Set<String> keySet() { return content.keySet(); } @Override public Collection<String> values() { return content.values(); } @Override public String put(final String key, final String value) { return content.put(key, value); } } 

Tada pridėkite šią klasę vietoj Map<String,String> , ir viskas bus patikrinta toje vietoje, kur rašote kodą. Nėra netikėtų ClassCastExceptions vėliau.

11
04 февр. Atsakymas pateikiamas Joachim Sauer 04 vasario mėn. 2009-02-04 19:59 '09 19:59 2009-02-04 19:59

Šiuo konkrečiu atveju aš nesaugysiu žemėlapių į „HttpSession“ tiesiogiai, o vietoj savo klasės egzemplioriaus, kuriame savo ruožtu yra žemėlapis (šios klasės įgyvendinimo detalės). Tada galite būti tikri, kad žemėlapio elementai yra tinkamo tipo.

Bet jei vis tiek norite patikrinti, ar Kortelės turinys yra teisingas, galite naudoti šį kodą:

 public static void main(String[] args) { Map<String, Integer> map = new HashMap<String, Integer>(); map.put("a", 1); map.put("b", 2); Object obj = map; Map<String, Integer> ok = safeCastMap(obj, String.class, Integer.class); Map<String, String> error = safeCastMap(obj, String.class, String.class); } @SuppressWarnings({"unchecked"}) public static <K, V> Map<K, V> safeCastMap(Object map, Class<K> keyType, Class<V> valueType) { checkMap(map); checkMapContents(keyType, valueType, (Map<?, ?>) map); return (Map<K, V>) map; } private static void checkMap(Object map) { checkType(Map.class, map); } private static <K, V> void checkMapContents(Class<K> keyType, Class<V> valueType, Map<?, ?> map) { for (Map.Entry<?, ?> entry : map.entrySet()) { checkType(keyType, entry.getKey()); checkType(valueType, entry.getValue()); } } private static <K> void checkType(Class<K> expectedType, Object obj) { if (!expectedType.isInstance(obj)) { throw new IllegalArgumentException("Expected " + expectedType + " but was " + obj.getClass() + ": " + obj); } } 
7
04 февр. atsakymą pateikė Esko Luontola 04 vasaris. 2009-02-04 02:19 '09 at 2:19 AM 2009-02-04 02:19

Štai trumpinamasis pavyzdys, kuriuo išvengiama įspėjimo apie „neišbandytą mesti“ naudojant dvi strategijas, paminėtas kituose atsakymuose.

  • Praleiskite palūkanų tipo klasę kaip parametrą vykdymo metu ( Class<T> inputElementClazz ). Tada galite naudoti: inputElementClazz.cast(anyObject);

  • Jei norite rinkti kolekcijų tipus, naudokite pakaitos simbolį? vietoj bendro tipo T, pripažinti, kad tikrai nežinote, kokių objektų tikėtis iš pasenusio kodo ( Collection<?> unknownTypeCollection ). Galų gale tai yra įspėjimas apie „nepažymėtą“ įspėjimą: negalime būti tikri, kad gausime Collection<T> , todėl sąžiningai, turime naudoti Collection<?> . Jei absoliučiai būtina, galite rinkti žinomo tipo Collection<T> knownTypeCollection ( Collection<T> knownTypeCollection ).

Paveldėtas kodas, susietas su toliau pateiktu pavyzdžiu, yra „input“ atributas „StructuredViewer“ („StructuredViewer“ yra medis arba lentelės valdiklis, „įvestis“ yra duomenų modelis). Šis „įvestis“ gali būti bet kokia „Java“ kolekcija.

 public void dragFinished(StructuredViewer structuredViewer, Class<T> inputElementClazz) { IStructuredSelection selection = (IStructuredSelection) structuredViewer.getSelection(); // legacy code returns an Object from getFirstElement, // the developer knows/hopes it is of type inputElementClazz, but the compiler cannot know T firstElement = inputElementClazz.cast(selection.getFirstElement()); // legacy code returns an object from getInput, so we deal with it as a Collection<?> Collection<?> unknownTypeCollection = (Collection<?>) structuredViewer.getInput(); // for some operations we do not even need a collection with known types unknownTypeCollection.remove(firstElement); // nothing prevents us from building a Collection of a known type, should we really need one Collection<T> knownTypeCollection = new ArrayList<T>(); for (Object object : unknownTypeCollection) { T aT = inputElementClazz.cast(object); knownTypeCollection.add(aT); System.out.println(aT.getClass()); } structuredViewer.refresh(); } 

Žinoma, aukščiau minėtas kodas gali suteikti klaidų, kai naudojame senąjį kodą su neteisingais duomenų tipais (pvz., Jei mes, kaip „Java“ kolekciją, nustatome masyvą kaip „StructuredViewer“ įvestį).

Metodo skambučio pavyzdys:

 dragFinishedStrategy.dragFinished(viewer, Product.class); 
5
13 авг. atsakymą pateikė StaticNoiseLog 13 rug . 2015-08-13 13:57 '15 , 13:57 2015-08-13 13:57

Objektai.Nepatikrinta naudingumo funkcija, esanti atsakyme į Esko Luontolą, yra puikus būdas išvengti netvarkos programoje.

Jei nenorite naudoti SuppressWarnings visam metodui, „Java“ verčia jus įdėti jį į vietinį. Jei jums reikia kompozicijos nariui, jis gali sukelti šį kodą:

 @SuppressWarnings("unchecked") Vector<String> watchedSymbolsClone = (Vector<String>) watchedSymbols.clone(); this.watchedSymbols = watchedSymbolsClone; 

Naudojimasis programa yra daug švaresnis, ir vis dar akivaizdu, ką darote:

 this.watchedSymbols = Objects.uncheckedCast(watchedSymbols.clone()); 

Pastaba: manau, svarbu pridurti, kad kartais įspėjimas iš tikrųjų reiškia, kad jūs darote kažką neteisingo:

 ArrayList<Integer> intList = new ArrayList<Integer>(); intList.add(1); Object intListObject = intList; // this line gives an unchecked warning - but no runtime error ArrayList<String> stringList = (ArrayList<String>) intListObject; System.out.println(stringList.get(0)); // cast exception will be given here 

Kompiliatoriaus pasakytina, kad ši peržiūra nebus tikrinama vykdymo metu, todėl paleisties trukmės klaida nebus padidinta, kol nebandysite pasiekti bendrų talpyklų duomenų.

4
11 авг. vartotojo889742 atsakymas 11 rug . 2011-08-11 16:53 '11, 16:53, 2011-08-11 16:53

Įspėjimas nėra sprendimas. Jūs neturėtumėte daryti dviejų lygių sprendimo viename pareiškime.

 HashMap<String, String> getItems(javax.servlet.http.HttpSession session) { // first, cast the returned Object to generic HashMap<?,?> HashMap<?, ?> theHash = (HashMap<?, ?>)session.getAttribute("attributeKey"); // next, cast every entry of the HashMap to the required type <String, String> HashMap<String, String> returingHash = new HashMap<>(); for (Entry<?, ?> entry : theHash.entrySet()) { returingHash.put((String) entry.getKey(), (String) entry.getValue()); } return returingHash; } 
4
10 марта '15 в 2:43 2015-03-10 02:43 atsakymas pateikiamas „ Abbas “ kovo 15 d. 15 val. 2:43 2015-03-10 02:43

Galbūt aš neteisingai suprato klausimą (pavyzdys ir pora aplinkinių linijų būtų gera), bet kodėl ne visada naudojate tinkamą sąsają (ir „Java5 +“)? Nematau jokios priežasties, kodėl jūs kada nors norėtumėte naudoti „ HashMap vietoj Map<KeyType,ValueType> . Tiesą sakant, aš negaliu pateikti jokios priežasties, kodėl HashMap kintamojo tipas būtų nustatytas vietoj Map .

Ir kodėl šaltinis? Ar tai yra paveldėto rinkinio parametrų tipas? Jei taip, naudokite generinius vaistus ir nurodykite norimą tipą.

2
04 февр. atsakymas pateikiamas vasario 04 d. 2009-02-04 01:05 '09, 1:05 2009-02-04 01:05

Paimkite jį, jis yra daug greičiau nei naujo HashMap sukūrimas, jei jis jau yra vienas, bet vis dar saugus, nes kiekvienas elementas yra patikrintas jo tipo ...

 @SuppressWarnings("unchecked") public static <K, V> HashMap<K, V> toHashMap(Object input, Class<K> key, Class<V> value) { assert input instanceof Map : input; for (Map.Entry<?, ?> e : ((HashMap<?, ?>) input).entrySet()) { assert key.isAssignableFrom(e.getKey().getClass()) : "Map contains invalid keys"; assert value.isAssignableFrom(e.getValue().getClass()) : "Map contains invalid values"; } if (input instanceof HashMap) return (HashMap<K, V>) input; return new HashMap<K, V>((Map<K, V>) input); } 
2
14 окт. atsakymas, kurį pateikė jfreundo spalio 14 d 2010-10-14 12:28 '10, 12:28, 2010-10-14 12:28

Greitai spėliokite, jei paskelbsite savo kodą, galite pasakyti tikrai, bet tu gali padaryti kažką linijose

 HashMap<String, Object> test = new HashMap(); 

kuris suteikia įspėjimą, kai jums reikia

 HashMap<String, Object> test = new HashMap<String, Object>(); 

tikriausiai verta pamatyti

Bendra Java programavimo kalbai

jei nesate susipažinę su tuo, kas turi būti padaryta.

2
04 февр. Mark Davidson atsakymas, pateiktas vasario 4 d. 2009-02-04 01:04 '09, 1:04, 2009-02-04 01:04

Jei reikia naudoti API, kuri nepalaiko Generics. Bandau atskirti šiuos skambučius apvyniojimo procedūrose su minimaliu eilių skaičiumi. Tada aš naudoju „SuppressWarnings“ komentarą ir tuo pat metu pridėkite saugos tipo priedą.

Tai tik asmeninis pageidavimas, kad viskas būtų kuo tvarkingesnė.

2
04 февр. Atsakymą pateikė Fortyrunner 04 vasaris. 2009-02-04 01:47 '09 ne 1:47 2009-02-04 01:47

Beveik kiekvieną kompiuterių mokslų problemą galima išspręsti pridedant netiesioginio lygio * ar kažko kito.

Taigi įveskite ne bendrinamą objektą, kurio lygis yra aukštesnis nei Map . Be konteksto tai neatrodo labai įtikinama, bet bet kuriuo atveju:

 public final class Items implements java.io.Serializable { private static final long serialVersionUID = 1L; private Map<String,String> map; public Items(Map<String,String> map) { this.map = New.immutableMap(map); } public Map<String,String> getMap() { return map; } @Override public String toString() { return map.toString(); } } public final class New { public static <K,V> Map<K,V> immutableMap( Map<? extends K, ? extends V> original ) { // ... optimise as you wish... return Collections.unmodifiableMap( new HashMap<String,String>(original) ); } } static Map<String, String> getItems(HttpSession session) { Items items = (Items) session.getAttribute("attributeKey"); return items.getMap(); } 

* Išskyrus pernelyg daug netiesioginio lygio.

1
04 февр. Atsakymą pateikė Tom Hawtin - tackline 04 vasaris. 2009-02-04 18:46 '09 at 18:46 PM 2009-02-04 18:46

Štai vienas iš būdų tai tvarkyti, kai nepaisysiu equals() operacijos.

 public abstract class Section<T extends Section> extends Element<Section<T>> { Object attr1;  @Override public boolean equals(Object obj) { if (obj == null) { // this exists, but obj doesn't, so they can't be equal! return false; } // prepare to cast... Section<?> other; if (getClass() != obj.getClass()) { // looks like we're comparing apples to oranges return false; } else { // it must be safe to make that cast! other = (Section<?>) obj; } // and then I compare attributes between this and other return this.attr1.equals(other.attr1); } } 

Atrodo, kad tai veikia „Java 8“ (netgi su -Xlint:unchecked )

1
30 янв. Atsakymą pateikė Jim Daehn 30 sausis 2015-01-30 03:15 '15 at 3:15 2015-01-30 03:15

Tiesiog įveskite tekstą prieš tai, kai pasakysite.

 Object someObject = session.getAttribute("attributeKey"); if(someObject instanceof HashMap) HashMap<String, String> theHash = (HashMap<String, String>)someObject; 

Ir tiems, kurie klausia, dažnai pakanka priimti objektus, kuriuose nesate tikri. Daugybė senų SOA diegimų vyksta aplink įvairius objektus, kurių ne visada turite pasitikėti. (Siaubo!)

EDIT Pakeista vieno pavyzdžio kodo versija, kad ji atitiktų plakatų atnaujinimus, ir po kai kurių komentarų matau, kad egzempliorius neveikia su generiniais vaistais. Tačiau keičiant čekį, kad patikrintumėte išorinį objektą, atrodo, gerai seka komandų eilutės kompiliatorius. Peržiūrėtas pavyzdys dabar paskelbtas.

1
04 февр. Atsakymą pateikė Rickas 04 vasaris. 2009-02-04 01:16 '09 ne 1:16 2009-02-04 01:16

„Android“ studijoje, jei norite išjungti tikrinimą, galite naudoti:

 //noinspection unchecked Map<String, String> myMap = (Map<String, String>) deserializeMap(); 
0
01 сент. Atsakymą pateikė Jan Moravec rugsėjo 1 d 2017-09-01 23:22 '17, 23:22 pm 2017-09-01 23:22

Jei esate tikras, kad seanso.getAttribute () grąžintas tipas yra „HashMap“, tuomet negalite pasinaudoti šio tikslaus tipo tipu, tačiau pasikliaukite tik bendru „HashMap“

 HashMap<?,?> getItems(javax.servlet.http.HttpSession session) { HashMap<?,?> theHash = (HashMap<?,?>)session.getAttribute("attributeKey"); return theHash; } 

Tada „Eclipse“ jus nustebins įspėjimais, tačiau, žinoma, tai gali sukelti sunkumų, kuriuos sunku derinti. Šį požiūrį naudoju tik kontekste, nepriklausomai nuo darbo.

0
12 июня '10 в 15:52 2010-06-12 15:52 Atsakymą pateikė Lukas Normantas birželio 12 d. 10 val. 15:52 2010-06-12 15:52

Problema čia:

 ... = (HashMap<String, String>)session.getAttribute("attributeKey"); 

session.getAttribute(...) - tai object kuris gali būti bet kas, bet kadangi jūs „žinote“ savo „ HashMap<String, String> , paprasčiausiai jį paliekate be pirmojo patikrinimo. Taigi įspėjimas. Kad būtų toks pedantinis, kurį „Java“ nori, kad būtumėte šiuo atveju, turite gauti rezultatą ir patikrinti jo suderinamumą su instanceof .

0
04 февр. atsakymas pateiktas JMD 04 vasario mėn. 2009-02-04 01:16 '09 ne 1:16 2009-02-04 01:16

Du būdai: vienas, kuris visiškai vengia žyma, o kitas - neklaužantis, bet malonus metodas.
Problema yra kolekcijų pregeneracija ...
Я верю, что эмпирическое правило: "бросать объекты по одному за раз" - что это означает при попытке использовать сырые классы в обобщенном мире, так это потому, что вы не знаете, что находится в этой Map <?,? > (и даже JVM может даже обнаружить, что это даже не карта!), это очевидно, когда вы думаете об этом, что не можете его отличить. Если у вас есть Map < String,? > map2, затем HashSet <String> keys = (HashSet <String> ) map2.keySet() не дает вам предупреждения, несмотря на то, что это был "акт веры" для компилятора (потому что он может оказаться TreeSet)... но это только a одиночный акт веры.

PS к возражению, что итерация, как на моем первом пути, "скучна" и "требует времени", ответ "без боли не получает": в обобщенной коллекции будет храниться Map.Entry < String, String > s и ничего остальное. Вы должны заплатить за эту гарантию. При систематическом использовании дженериков этот платеж, красиво, принимает форму соответствия кодированию, а не машинного времени!
Одна школа мысли может сказать, что вы должны установить настройки Eclipse, чтобы делать такие неконтролируемые ошибки при отправке, а не предупреждения. В этом случае вам придется использовать свой первый способ.

 package scratchpad; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Vector; public class YellowMouse { // First way Map<String, String> getHashMapStudiouslyAvoidingSuppressTag(HttpSession session) { Map<?, ?> theHash = (Map<?, ?>)session.getAttribute("attributeKey"); Map<String, String> yellowMouse = new HashMap<String, String>(); for( Map.Entry<?, ?> entry : theHash.entrySet() ){ yellowMouse.put( (String)entry.getKey(), (String)entry.getValue() ); } return yellowMouse; } // Second way Map<String, String> getHashMapUsingNaughtyButNiceUtilityMethod(HttpSession session) { return uncheckedCast( session.getAttribute("attributeKey") ); } // NB this is a utility method which should be kept in your utility library. If you do that it will // be the *only* time in your entire life that you will have to use this particular tag!! @SuppressWarnings({ "unchecked" }) public static synchronized <T> T uncheckedCast(Object obj) { return (T) obj; } } 
0
ответ дан mike rodent 21 марта '11 в 22:09 2011-03-21 22:09