0

I have this code:

Map<Object, Object> map;
...
List<String> strings = new ArrayList<>();
Object tmp = map.get("strings");
strings.addAll((List<String>) tmp);

It works fine if tmp is of type List<String>, but why the program won't produce exception if tmp is of type List<Map>?

Two Horses
  • 1,401
  • 3
  • 14
  • 35

1 Answers1

3

A cast to List<String> of an Object actually is a cast to List. At runtime String no longer is there. The IDE did warn about this. Later on when working with strings items a runtime exception may be expected.

Another thing, List<Map> misses generic parameters, and when used bare, like List list, the compiler reverts to non-generic interpretation, dropping all warning of generic type violations.

For your use-case: a kind of simple "variable" map with differently typed variables is problematic. Provide your own run-time type info, and maybe revert to (actually unneeded) shoveling of data:

List<?> list = (List<?>) map.get("strings");
List<String> list2 = list.stream().map(String.class::cast).collect(Collectors.toList());
luk2302
  • 55,258
  • 23
  • 97
  • 137
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • What do you mean by "misses generic parameters, and when used bare"? And i don' t understand how to ensure that i assign only List of Strings to my variable – Two Horses Sep 01 '20 at 11:10
  • 4
    The concept you're looking for is called "type erasure", you should be able to find some good documentation about it online. Short version: type parameters do not exist at runtime, they are only checked at compile time, this is a technical limitation of the JVM. Generics are not a concept that existed in Java 1.0, they were added later and thus are not as integral to the design of the language as many people assume. –  Sep 01 '20 at 11:34