Is there any way to avoid the constructor passing the class?

Consider this HashMap extension (it generates an instance of class V when it calls "get" if it is null)

public class HashMapSafe<K, V> extends HashMap<K, V> implements Map<K, V>{ private Class<V> dataType; public HashMapSafe(Class<V> clazz){ dataType = clazz; } @SuppressWarnings("unchecked") @Override public V get(Object key) { if(!containsKey(key)){ try { put((K)key, dataType.newInstance()); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return super.get(key); } } 

Using this is something like this

 Map<String,Section> sections = new HashMapSafe<String,Section>(Section.class); sections.get(sectionName); //always returns a Section instance, existing or new 

It seems to me that I'm a little redundant to supply the "Section" twice, once as a generic type, and also supply it with a class. I suppose this is not possible, but is it possible to implement HashMapSafe (while maintaining the same functionality) so that it can be used like this?

 Map<String,Section> sections = new HashMapSafe<String,Section>(); 

Or how is it ?:

 Map<String,Section> sections = new HashMapSafe<String>(Section.class); 
+6
java generics
source share
5 answers

You cannot improve the use of the constructor due to type erasure, as others have already pointed out, but you must improve verbosity using the static factory method instead of the constructor ...

I am not in front of the compiler, and I can never get method type parameters on the first try, but it will look something like this ...

 public static <K,V> Map<K,V> create( Class<V> cl ) { return new HashMapSafe<K,V>(cl); } ... Map<String,Section> sections = HashMapSafe.create(Section.class); 
+6
source share

No no. Java does not have Reified generics .

Guava has, however, a nice solution in MapMaker#makeComputingMap() flavor

 Map<String, Integer> numbers = new MapMaker().makeComputingMap(new Function<String, Integer>() { public Integer apply(String key) { return 0; } }); 

Which set returns 0 instead of null when the key is absent (and it is thread safe, unlike your solution).

+3
source share

Impossible. The first of them would require to do something like new V() , and this is impossible. The second may require the installation of type V at run time, since it is passed in the constructor, which is also impossible to do. Keep in mind that generators use compile time and they are deleted at runtime.

+1
source share

I found this article interesting: Generic Reflection

in short:

  public abstract class AbstractUserType<T> implements UserType { ... public Class returnedClass { ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperClass(); return (Class) parameterizedtype.getActualTypeArguments()[0]; } ... } 
+1
source share

Is there any way to avoid the constructor passing the class?

In short, No.

The main reason is "type erasure". At run time, the HashMapSafe implementation does not have implicit knowledge of types matching type parameters. This information is erased. If you need an implementation to find out what type it is, you need to pass it as a Class object compatible with Class<V> .

 Map<String,Section> sections = new HashMapSafe<String,Section>(); 

This does not work due to erasing styles; see above.

 Map<String,Section> sections = new HashMapSafe<String>(Section.class); 

This does not work because the Java language requires that you specify a type (or wildcard) for all type parameters when using this syntax.

0
source share

All Articles