This is a small snippet of code taken from some of the examples that accompany the Stanford Parser. I've been developing in Java for about 4 years, but have never had a very strong understanding of what this style of code is supposed to indicate.
List<? extends HasWord> wordList = toke.tokenize();
I'm not worried about the details of the code. What I'm confused about is what exactly the generic expression is supposed to convey, in English.
Can someone explain this to me?
A question mark is a signifier for 'any type'.
?
alone meanswhile your example above means
List<? extends HasWord>
accepts any concrete classes that extends HasWord. If you have the following classes...... the
wordList
can ONLY contain a list of either As or Bs or mixture of both because both classes extend the same parent ornull
(which fails instanceof checks forHasWorld
).Perhaps a contrived "real world" example would help.
At work we have rubbish bins that come in different flavours. All bins contain rubbish, but some bins are specialist and do not take all types of rubbish. So we have
Bin<CupRubbish>
andBin<RecylcableRubbsih>
. The type system needs to make sure I can't put myHalfEatenSandwichRubbish
into either of these types, but it can go into a general rubbish bin ``Bin. If I wanted to talk about a
Binof
Rubbishwhich may be a specialist so I can't put in incompatible rubbish, then that would be
Bin`.(Note:
? extends
does not mean read-only. For instance, I can with proper precautions take out a piece of rubbish from a bin of unknown speciality and later put it back in a different place.)Not sure how much that helps. Pointer-to-pointer in presence of polymorphism isn't entirely obvious.
means "A class/interface that extends
HasWord
." In other words,HasWord
itself or any of its children... basically anything that would work withinstanceof HasWord
plusnull
.In more technical terms,
? extends HasWord
is a bounded wildcard, covered in Item 31 of Effective Java 3rd Edition, starting on page 139. The same chapter from the 2nd Edition is available online as a PDF; the part on bounded wildcards is Item 28 starting on page 134.Update: PDF link was updated since Oracle removed it a while back. It now points to the copy hosted by the Queen Mary University of London's School of Electronic Engineering and Computer Science.
Update 2: Lets go into a bit more detail as to why you'd want to use wildcards.
If you declare a method whose signature expect you to pass in
List<HasWord>
, then the only thing you can pass in is aList<HasWord>
.However, if said signature was
List<? extends HasWord>
then you could pass in aList<ChildOfHasWord>
instead.Note that there is a subtle difference between
List<? extends HasWord>
andList<? super HasWord>
. As Joshua Bloch put it: PECS = producer-extends, consumer-super.What this means is that if you are passing in a collection that your method pulls data out from (i.e. the collection is producing elements for your method to use), you should use
extends
. If you're passing in a collection that your method adds data to (i.e. the collection is consuming elements your method creates), it should usesuper
.This may sound confusing. However, you can see it in
List
'ssort
command (which is just a shortcut to the two-arg version of Collections.sort). Instead of taking aComparator<T>
, it actually takes aComparator<? super T>
. In this case, the Comparator is consuming the elements of theList
in order to reorder the List itself.In English:
In general the
?
in generics means any class. And theextends SomeClass
specifies that that object must extendSomeClass
(or be that class).The question mark is used to define wildcards. Checkout the Oracle documentation about them: http://docs.oracle.com/javase/tutorial/java/generics/wildcards.html