Ensuring generic wildcards match in Java -


so understanding following:

hashmap<class<?>,list<?>> map 

would allow insert pairing. how enforce can insert matched pairs. e.g.

map.put(string.class, new vector<string>()); map.put(integer.class, new vector<integer>()); 

but disallow following:

map.put(classa.class, new vector<classb>()); //i want refuse compile 

is possible?

update: input far. understand abstracting away map insertion enforce common type across both parameters. keep map clean, how can guarantee compiler case.

e.g. cause compiler grumble, , no amount of casting seems fix (at least i've tried)

list<string> list1 = map.get(string.class); 

so instead i'm using following i'm not happy it

list list2 = map.get(string.class); 

nb i'm not in front of ide memory general idea clear.

i not directly use hashmap, default methods has not allow desire. i'd write own collection based on hashmap expose it's own put method. this:

public <t> void put(class<t> clazz, list<t> list) {     internalmap.put(clazz, list); } 

assume internalmap private member of collection class , of type hashmap<class<?>, list<?>>. notice use of generic parameter method. call that:

mycollection.<integer>put(integer.class, new vector<integer>()); mycollection.<string>put(string.class, new vector<string>()); 

or that:

mycollection.put(integer.class, new vector<integer>()); mycollection.put(string.class, new vector<string>()); 

these not compile:

mycollection.<string>put(string.class, new vector<integer>()); mycollection.put(string.class, new vector<integer>()); 

update regarding latest comment op on question, , update of question itself:

how make more generic. e.g. replace list generic type defined @ class level. public void put (class clazz, t1 t1)...how ensure t1 can handle generic parameter?

well, can still this, additional generic parameter , type constraint. need use root base class or interface collection have, because need enforce generics appropriately. let's assume base type collection<t> interface (vector, arraylist , many other collections implement interface). above put method (i including imaginary class internalmap definition):

public class classmap {      private map<class<?>, collection<?>> internalmap          = new hashmap<class<?>, collection<?>>();      public <t, tcollection extends collection<t>> void put(             class<t> clazz,              tcollection collection) {         internalmap.put(clazz, collection);     }      public <t> collection<t> get(class<t> clazz) {         // notice cast, important hide         // "compiler grumble" mention in post         return (collection<t>) internalmap.get(clazz);     } } 

the usage update cases explicit generic arguments:

mycollection.<integer, vector<integer>>put(integer.class, new vector<integer>()); mycollection.<string, arraylist<string>>put(string.class, new arraylist<string>()); 

and shorter version:

mycollection.put(integer.class, new vector<integer>()); mycollection.put(string.class, new arraylist<string>()); 

will work, due generic type inference.

the get method, must have noted, uses collection<t> interface. if introduce tcollection generic argument in same manner in put method, have supply generic arguments. so, if method defined this:

public <t, tcollection extends collection<t>> tcollection get(class<t> clazz) {     return (tcollection) internalmap.get(clazz); } 

then have 2 problems:

  • the call needs necessary ugliness:
arraylist<string> list 
 = mycollection.<string, arraylist<string>>get(string.class);
  • you have no compile-time guarantee collection arraylist<string> (and thinking compile-time type safety important you), receive runtime-exception invalid cast if wrong. therefore, get method not need introduce tcollection generic argument @ all, guaranteed work collection<t> interface (as values implement it). if interface not suitable (you need specific methods of , etc), you'd have either cast explicitly (with risks in mind), or use more-concrete interface root type constraint of tcollection. instance, instead of collection<t>, can use list<t>.

as bottom line, regarding use of tcollection generic argument, can omitted. once add collection map, no longer know exact implementation used. so, above code same this:

public class classmap {      private map<class<?>, collection<?>> internalmap          = new hashmap<class<?>, collection<?>>();      public <t> void put(class<t> clazz, collection<t> collection) {         internalmap.put(clazz, collection);     }      public <t> collection<t> get(class<t> clazz) {         return (collection<t>) internalmap.get(clazz);     } } 

and used that:

mycollection.<integer>put(integer.class, new vector<integer>()); mycollection.<string>put(string.class, new arraylist<string>()); 

or that:

mycollection.put(integer.class, new vector<integer>()); mycollection.put(string.class, new vector<string>()); 

that same kocko's suggested answer


Comments

Popular posts from this blog

windows - Single EXE to Install Python Standalone Executable for Easy Distribution -

c# - Access objects in UserControl from MainWindow in WPF -

javascript - How to name a jQuery function to make a browser's back button work? -