-1

I have a List that was initialised without any parameters. I added Map<String, Object> to that list.

Then I created a User object, and I know after typecasting the list to List<User> at compile time.

But I am surprised, I didn't get those errors at runtime either.

To give you an example the code is below:

I was expecting an error on the line List<User> users = (List<User>) list;

Instead, the list users still remains a List<Map<String, Object>>

The following code runs perfectly fine.

import java.util.HashMap;
import java.util.List;
import java.util.Map;

class User {
    private String name;
    public String getName(){
        return name;
    }
}

public class Main {
    public static void main(String[] args) {


        Map<String, Object> map1 = new HashMap<>();
        map1.put("name", "Bruce");
        Map<String, Object> map2 = new HashMap<>();
        map2.put("name", "Clark");
        List list = List.of(map1, map2);
        List<User> users = (List<User>) list;
        System.out.println(users.get(0) instanceof Map);

    }
}

Output:

true

What am I missing here?

Also, I do get ClassCastException when I try to access the objects from the said users list.

For example, if I do users.get(0).getName() I get a nice ClassCastException

java.lang.ClassCastException: class java.util.HashMap cannot be cast to class User

But not before that.

So users.get(0) is still a HashMap

Can someone shine a light on why this happens?

Anurag Wagh
  • 1,086
  • 6
  • 16
  • 3
    Ever heard of type erasure? Because of that, the runtime cannot verify whether the cast to `List` is valid, and hence cannot throw an exception. It is only when you try to access `getName`, that it tries to (implicitly) cast `users.get(0)` to `User`. This cast _can_ be verified, and after it is found that it is invalid, an exception is thrown. Does [this](https://stackoverflow.com/q/2693180/5133585) answer your question? – Sweeper Sep 23 '21 at 09:02
  • "What am I missing here" did you notice the unchecked cast warning? Do you understand what "unchecked" means in this context, i.e. why the cast *can't* be checked? – Andy Turner Sep 23 '21 at 09:41
  • Did not get any warnings from IDE or when I compiled @AndyTurner Tried it on Jshell as well still no warnings – Anurag Wagh Sep 23 '21 at 09:45
  • @AnuragWagh check your settings to ensure that you have warnings enabled. That is definitely an unchecked cast, and you should be warned about it. – Andy Turner Sep 23 '21 at 09:48

1 Answers1

0

With the first pre-generic usage (list), the compiler no longer does type safe generics.

    List list = List.of(map1, map2);
    List<User> users = (List<User>) list;
    System.out.println(users.get(0) instanceof Map);

So users is just a List of Object.

(Generic casts are not real casts anyway, more metadata provided for the compiler, not code bearing - because of type-erasure at run-time.)

user207421
  • 305,947
  • 44
  • 307
  • 483
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138