If you've got a List<? extends Animal> reference, then you know it references a List of a specific type that is Animal or a subclass. Which means it can be a List<Animal>, a List<Dog>, a List<Cat>, a List<Snake> etc. So what can you safely add into all those? Nothing.
If you want a List that you can add any Animal to, then what you want is simply a List<Animal>. If you want a reference that can hold any List that can definitely contain any Animal, then the most general type is List<? super Animal> (which can reference either a List<Object> or List<Animal>).
The important point here - and it explains the problem you were originally having - is that wildcards only apply to references. The actual List has a specific type. When you wrote new ArrayList<>(), it would actually be interpreted as new ArrayList<Animal>().
I’ve looked at a lot of different solutions, and in my humble opinion Aspose is the way to go. Here’s the link: http://aspose.com
subject: Generics: problem with Lists when using wildcards