Why does this nested generic cast cause a compiler error

Mark Jeronimus :

Excuse me if this was asked before (I'm almost sure) but I can't find the right keywords or dig it up from the pile of unrelated generics questions.

In short

This works:

Object      a = null;
Set<Object> b = (Set<Object>)a;

so why does this give a compiler error?

Set<Object>      c = null;
Set<Set<Object>> d = (Set<Set<Object>>)c;

and why is this simple workaround valid?

Set<Object>      e = null;
Set<?>           f = (Set<?>)e;
Set<Set<Object>> g = (Set<Set<Object>>)f;

Long version: (kept for legacy but no longer relevant to the question)

I have a library method that returns a Map<Number, Object> of a preprocessed JSON message. After manual deep-type-checking, I need to cast and return it as Map<Number, Map<String, Map<String, Object>>>, expecting an unchecked cast warning which I can ignore because I've just checked it.

However I'm getting the compiler error:

Error:(61, 10) java: Cannot cast from java.util.Map<java.lang.Number,java.lang.Object> to java.util.Map<java.lang.Number,java.util.Map<java.lang.String,java.util.Map<java.lang.String,java.lang.Object>>>

or in a more readable form (based on the error in the IDE):

Inconvertible types; cannot cast 'Map<Number,Object>' to 'Map<Number,Map<String,Map<String,Object>>>')

[edit] Changed from a how-to question to a why-question.

Sweeper :

Note that since generic types are erased at runtime, nothing substantial actually happens when you do these casts. It's really all boils down to "does the compiler allow this?"

One of the aims of generics is to ensure type safety. If you could, for some reason, assign List<List<Object>> to List<Object>, you'd lose type safety:

List<List<Object>> listOfLists = new ArrayList<>();
List<Object> list = listOfLists; // suppose this is valid
list.add(new Object());
listOfLists.get(0); // what happens here?

(I am using lists here for convenience. You can easily apply this to maps or sets or any other generic type)

listOfLists.get(0) would return an instance of Object, as that is what we added, but it wouldn't! Because its type is List<List<Object>>! This is why being able to cast like this undermines type safety.

However, the two casts below are valid:

List<Object>      e = null;
List<?>           f = (List<?>)e;
List<List<Object>> g = (List<List<Object>>)f;

List<?> f means "f is a List of some class that extends Object, but that class could be anything". Note that List<?> is different from List<Object>. You can't do f.add("String") because ? is not necessarily a String, is it?

The first cast is allowed for the same reason why most people (incorrectly) believes that List<String> can be assigned to List<Object>. In fact, this cast is not needed. A List<String> is a List of stuff that extends Object.

The second cast is you telling the compiler that you know what the ? is, and it is List<Object>. The compiler warns you that you might be wrong about what ? is by issuing an unchecked warning.

In a sense, you are kind of asking why you can't cast directly from Integer to String, but can first cast from Integer to Object then to String.

I feel like your confusion might be caused by a misunderstanding of the differences between <Object> and <?>. This post might be worth reading.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Java

Why does using a base class for a method reference cause a compiler error

From

Why does the statement "2i;" NOT cause a compiler error?

From Dev

Why does not capitalizing the class name cause a compiler error here?

From Dev

Why does a function in nested XPATH conditional cause the error?

From Dev

When does "requires" cause a compiler error

From Java

Why does an empty lambda and constructor with an explicit return cause a compiler error (Java Bug?)

From Dev

Why does this conditional cause an error?

From Java

Why does =+ not cause a compile error?

From Dev

Why does this subquery NOT cause an error?

From Dev

Why does the compiler not infer the generic type

From Dev

Casting Generic Types - Why does a direct cast with parenthesis "()" give a compile-error, but casting with the "as"-keyword works?

From Dev

Why does the Swift Compiler throw an error on inferring the type of my Generic Element when the Element is clearly constrained?

From Dev

Why does the Rust compiler request I constrain a generic type parameter's lifetime (error E0309)?

From Dev

Why does this cause a segmentation error and that does not?

From Dev

Why does this Ownership transfer does not cause an error?

From Dev

Why does adding removing an index in the for loop condition cause an error in the nested if statement?

From Dev

Why java circular generic spec does not allow to cast "this" into generic instance

From Dev

Array of Nested Type: Why Does the Compiler Complain?

From Dev

Why does creating SimpleImmutableMap cause unchecked cast warning?

From Dev

Does delete[] work properly with generic arrays? If so why does using std::vector::erase on it cause error in freeing memory

From Java

Why does compiling this code cause a compiler stack overflow?

From Dev

Why does putting a multidimensional array in varargs cause a compiler warning?

From Dev

Why does 0b1111_1111 cause a compiler error "int cannot be converted to byte" but not 0b111_1111?

From Dev

Why does this sequence of pointer operations cause an error?

From Javascript

Why does 00.0 cause a syntax error?

From Java

why does comma(,) not cause to compilation error?

From

Why does "try" not cause an undefined subroutine error?

From

Why does this version tag cause an error?

From Dev

Why does casting cause the error to go away?

Related Related

  1. 1

    Why does using a base class for a method reference cause a compiler error

  2. 2

    Why does the statement "2i;" NOT cause a compiler error?

  3. 3

    Why does not capitalizing the class name cause a compiler error here?

  4. 4

    Why does a function in nested XPATH conditional cause the error?

  5. 5

    When does "requires" cause a compiler error

  6. 6

    Why does an empty lambda and constructor with an explicit return cause a compiler error (Java Bug?)

  7. 7

    Why does this conditional cause an error?

  8. 8

    Why does =+ not cause a compile error?

  9. 9

    Why does this subquery NOT cause an error?

  10. 10

    Why does the compiler not infer the generic type

  11. 11

    Casting Generic Types - Why does a direct cast with parenthesis "()" give a compile-error, but casting with the "as"-keyword works?

  12. 12

    Why does the Swift Compiler throw an error on inferring the type of my Generic Element when the Element is clearly constrained?

  13. 13

    Why does the Rust compiler request I constrain a generic type parameter's lifetime (error E0309)?

  14. 14

    Why does this cause a segmentation error and that does not?

  15. 15

    Why does this Ownership transfer does not cause an error?

  16. 16

    Why does adding removing an index in the for loop condition cause an error in the nested if statement?

  17. 17

    Why java circular generic spec does not allow to cast "this" into generic instance

  18. 18

    Array of Nested Type: Why Does the Compiler Complain?

  19. 19

    Why does creating SimpleImmutableMap cause unchecked cast warning?

  20. 20

    Does delete[] work properly with generic arrays? If so why does using std::vector::erase on it cause error in freeing memory

  21. 21

    Why does compiling this code cause a compiler stack overflow?

  22. 22

    Why does putting a multidimensional array in varargs cause a compiler warning?

  23. 23

    Why does 0b1111_1111 cause a compiler error "int cannot be converted to byte" but not 0b111_1111?

  24. 24

    Why does this sequence of pointer operations cause an error?

  25. 25

    Why does 00.0 cause a syntax error?

  26. 26

    why does comma(,) not cause to compilation error?

  27. 27

    Why does "try" not cause an undefined subroutine error?

  28. 28

    Why does this version tag cause an error?

  29. 29

    Why does casting cause the error to go away?

HotTag

Archive