fork download
  1. import java.lang.reflect.Field;
  2. import java.lang.reflect.ParameterizedType;
  3. import java.lang.reflect.Type;
  4. import java.util.HashMap;
  5. import java.util.HashSet;
  6. import java.util.Map;
  7. import java.util.Set;
  8.  
  9. class Foo {}
  10. class Bar {}
  11. interface MyValidMap extends Map<Foo, Set<Bar>> {}
  12.  
  13. class Ideone {
  14. public final HashMap<Foo, HashSet<Bar>> good = null;
  15. public final Map<Foo, Set<Bar>> better = null;
  16. public final String notAMap = null;
  17. public final Map<String, Set<Bar>> badKey = null;
  18. public final Map<Foo, String> badValue = null;
  19. public final Map<Foo, Set<String>> badSetElems = null;
  20. public final MyValidMap noTypeParamMap = null;
  21.  
  22. public static void main(String[] args) throws Exception {
  23. for (Field field : Ideone.class.getFields()) {
  24. System.out.println(field.getName() + " - " + fieldMatches(field));
  25. }
  26. }
  27.  
  28. private static String fieldMatches(Field mapField) throws Exception {
  29. if (!Map.class.isAssignableFrom(mapField.getType())) {
  30. return "Field is not a Map";
  31. }
  32.  
  33. if (!(mapField.getGenericType() instanceof ParameterizedType)) {
  34. // We know it's a map, but it doesn't have type params. Probably something
  35. // like this: class MyStringMap implements Map<String, String>. You can do
  36. // something with getGenericInterfaces() but this seems so unlikely that
  37. // it could just be ignored.
  38. return "TODO";
  39. }
  40.  
  41. final ParameterizedType mapType = (ParameterizedType) mapField.getGenericType();
  42. final Type keyType = mapType.getActualTypeArguments()[0];
  43. final Type valueType = mapType.getActualTypeArguments()[1];
  44. if (Foo.class != keyType) {
  45. return "Map's key type is not Foo";
  46. }
  47.  
  48. if (!(valueType instanceof ParameterizedType)) {
  49. // Same problem as above. May be a Set without type params
  50. return "Map's value is (probably) not a Set";
  51. }
  52.  
  53. final ParameterizedType pValueType = (ParameterizedType) valueType;
  54. final Class<?> valueClass = pValueType.getRawType() instanceof Class ?
  55. ((Class<?>) pValueType.getRawType()) :
  56. Ideone.class.getClassLoader().loadClass(
  57. pValueType.getRawType().getTypeName()
  58. );
  59.  
  60. if (!Set.class.isAssignableFrom(valueClass)) {
  61. return "Map's value is not a Set";
  62. }
  63.  
  64. final Type setElemType = pValueType.getActualTypeArguments()[0];
  65. if (setElemType != Bar.class) {
  66. return "Set's elements are not Bars";
  67. }
  68. return "Looks good";
  69. }
  70. }
  71.  
Success #stdin #stdout 0.1s 52996KB
stdin
Standard input is empty
stdout
good - Looks good
better - Looks good
notAMap - Field is not a Map
badKey - Map's key type is not Foo
badValue - Map's value is (probably) not a Set
badSetElems - Set's elements are not Bars
noTypeParamMap - TODO