I was reading a discussion about C++ templates and C# generics, and how they are different from Java's type-erased generics. I read a statement that said that Java still uses casting at runtime, for instance when dealing with collections. If this is true, I wasn't aware of it!

Let's say that I have code such as:

```
ArrayList<SomeClass> list = new ArrayList<SomeClass>();
...
SomeClass object = list.get(0);

```

My question is. Is this effectively compiled to

```
ArrayList list = new ArrayList();
...
SomeClass object = (SomeClass) list.get(0);

```

If so, why? I thought that the fact that list is of type `ArrayList<SomeClass>` guarantees, at compile time and run time, that only SomeClass will be stored inside the ArrayList? Or can you ever do unsafe type-casting to transform an `ArrayList<OtherClass>` into an `ArrayList<SomeClass>`?

Are there other occasions where at-runtime type casting is done in Java generics?

Finally, if casting at run time is indeed used, are there occasions when the JIT can elide the run time cast check?

(Please refrain from answering/commenting that micro-optimisations are not worth it, preemptive optimisation is root of all evil, etc. I see these on other similar questions. These points are well understood, but they do not take away the point of trying to understand how type-erased generics are implemented under the hood.)