ArrayList<? extends A> foo = new ArrayList<B>();
Список A - это не то же самое, что Список B, потому что вы не можете гарантировать согласованность содержимого в списке.
А именно, если бы это было возможно, вы могли бы вставить элемент типа A в список, экземпляр которого был создан только для содержания элементов B.
Конечно, приведенная выше декларация не позволит вам записать какие-либо элементы в список.Это объявление только для чтения.
Также хорошим принципом ООП является объявление переменных как интерфейсов, а не реализаций:
List<? extends A> foo = new ArrayList<B>();