Collection <? extends T> vs Collection <T>

Trying to understand the concepts in Spring MVC , I came across the expression Collection<? extends Book> Collection<? extends Book> , which I have never seen before. I tried to figure it out on my own, but I don't see the difference between using Collection<? extends Book> Collection<? extends Book> and Collection<Book> . I assumed that this is only allowed for Book extensions, but it also allows the Book. So scratch it. I tried to use Google, but since? is a wildcard in google, so searching is almost impossible. I was looking for stackoverflow for an answer, but all questions about this (e.g. List <? Extends MyType> and <? Extends> Java syntax ) already accept knowledge of Collection<? extends T> Collection<? extends T> . Here is the code that originally intrigued my interest:

 import java.util.ArrayList; import java.util.Collection; public class Book { public static void main(String[] args) { BookCase bookCase1 = new BookCase(); BookCase bookCase2 = new BookCase(bookCase1); } } class BookCase extends ArrayList<Book> { public BookCase() { } //acts same as public BookCase(Collection<Book> c) { public BookCase(Collection<? extends Book> c) { super(c); } } 

What does <? extends T> <? extends T> ? How is it different from <T> ?

EDIT:

Follow-up question: Does BookCase extends ArrayList<Book> BookCase extends Book ?

+6
source share
5 answers

Consider the following

 class Animal { } class Horse extends Animal { } private static void specific(List<Animal> param) { } private static void wildcard(List<? extends Animal> param) { } 

Without extends syntax, you can only use the exact class in the signature

  specific(new ArrayList<Horse>()); // <== compiler error 

With a wildcard extension, you can allow any subclasses of Animal

  wildcard(new ArrayList<Horse>()); // <== OK 

Generally better to use? extends the syntax as it makes your code more reusable and future.

+3
source

Check out this from the documentation.

In general, if Foo is a subtype (subclass or subinterface) of Bar, and G is a generic type declaration, this is not the case when G is a subtype of G. This is probably the most difficult thing you need to learn about generics, because it is contrary to our deep-rooted intuition.

See the next page about wildcards .

So basically, when you write void doStuff(List<Book>){} , you can only do things in the list of Book objects ONLY.

Not Novel s, not Magazine s, not ComicBook s.

Again, this is because although Novel continues to Book , G<Novel> does not actually extend G<Book> . This is not very intuitive, but the example in the documentation will help you see it.

+4
source

Both Collection<Book> and Collection<? extends Book> Collection<? extends Book> represent a collection in which Book instances and objects can be stored that can be read from Book through an is-strong connection. This property also extends to interfaces.

The difference here is that the latter form is considered limited. Depending on the binding, you cannot add or remove items from this collection.

? extends T ? extends T is the upper bounded wildcard . Essentially, it describes a hierarchical binding between some type ( ? ) At the lower end and Book at the upper end. It is included, so you can store instances of Book there, but if you had other classes and interfaces, for example:

 class Novella extends Book {} class Magazine extends Book {} class ComicBook extends Book{} class Manga extends Magazine {} class Dictionary extends Book {} class ForeignLanguageDictionary<T extends Language> extends Dictionary {} interface Language {} 

... can you find any of these instances inside Collection<? extends Book> Collection<? extends Book> .

Remember that I mentioned that you cannot add or remove things from this collection? Remember this convention:

producer prolongs; consumer super.

Please note that this is in terms of collection; if the collection is limited to extends , it is the manufacturer; if it is limited to super , it is a consumer.

However, from the point of view of this collection, he has already prepared all his notes, so you cannot add new ones to it.

 List<? extends Book> books = new ArrayList<>(); // permanently empty books.add(new Book()); // illegal 

If you connected it with ? super Book ? super Book , you would not be able to extract elements from it in a reasonable way - you would need to get an Object instead, which is not short.

 List<? super Book> books = new ArrayList<>(); books.add(new Book()); books.add(new Manga()); Book book = books.get(0); // can't guarantee what Book I get back 

Basically, if you are involved with ? super T ? super T , you only ever intend to insert elements into this collection.

The next question is: Does BookCase extends ArrayList<Book> BookCase extends Book ?

No. A BookCase in this case is an ArrayList , not a Book . It so happened that the list of arrays is associated with the storage of books, but he himself is not a Book .

+3
source

Here's an example that clearly shows the difference between Collection<? extends Book> Collection<? extends Book> and Collection<Book> :

 public class Test { public static void main(String[] args) { BookCase bookCase1 = new BookCase(); BookCase bookCase2 = new BookCase(bookCase1); List<FictionBook> fictionBooks = new ArrayList<>(); BookCase bookCase3 = new BookCase(fictionBooks); } } class Book {} class FictionBook extends Book {} class BookCase extends ArrayList<Book> { public BookCase() { } //does not act same as public BookCase(Collection<Book> c) { public BookCase(Collection<? extends Book> c) { super(c); } } 

this code compiles. If you change the BookCase constructor BookCase to Collection<Book> , this example will not compile.

+2
source

List<Book> - a list that can contain any book. Since there are no restrictions on the book, you can add any book to it.

List<? extends Book> List<? extends Book> is also a list containing books, but there may be additional restrictions. Maybe this is actually a List<PoetryBook> , and it can only store instances of PoetryBook , you can be sure that every item inside this list is a book. Due to this possible limitation, you cannot add any items to this list.

Consider a method that takes a list of books and returns the book with the most pages.

 Book getBookWithMostPages(List<? extends Book>) { ... } 

This method can be called using List<Book> or using List<PoetryBook> .

If you change the signature to

 Book getBookWithMostPages(Iterable<? extends Book>) { ... } 

then it can also be used with Set<ScienceBook> or anything that is iterable and contains books.

0
source

Source: https://habr.com/ru/post/982347/


All Articles