"Says this reference can be initialized with Animal or anything that extends Animal e.g. CAT, DOG, etc. This was about initialization.
But once initialization is done, compiler has no idea what this reference is initialized to, It can be anyone from CAT, DOG, or Animal. Since It is not sure that what object type is this, compiler gives compilation error.
Generics was introduced for type safety, so that you can detect and prevent "possible" runtime errors at compile time.
Also, compiler adds required casts whenever necessary so, no explicit casting is required.
When you write this statement, you are saying that genericExtends can be assigned to any List-type which holds Objects of type Animal or its sub classes. So, the only thing you are guaranteeing to the compiler is that the UPPER BOUND of the type in the list will be Animal.
Compiler cant allow you to add any object to this list, because it does NOT know the actual type of List that you assign at Run time. Add operation will have the risk of ClassCastException. For e.g.:
Compiler will allow you to get/read an object from this list, because it knows that the object returned will be atleast of type B or Animal(in your case). So the cast will never fail.