Confused by the following data type - java

List<? extends List<? extends ObservationInteger>>
Just to give you a background which probably has nothing to do with the question. Trying to use the JAHMM library to build and score HMM's.
One of the parameters to the functions mentions the above as the datatype and I have no idea what it means.
From what I understand with help from a friend
List<? extends ObservationInteger> means a List of instances of any classes extending "ObservationInteger" which is a valid class in the library.
It is the outer List<? extends List<?... that is confusing me.
Can someone throw some light on this?

List<? extends List... means that it can be List of any Collections implementing List interface.
List<List<? extends ObservationInteger>> list = new ArrayList<List<ObservationInteger>>(); - compiler error because without ? extends compiler requires exact match:
List<List<? ObservationInteger>> list = new ArrayList<List<? extends ObservationInteger>>(); - OK
but this looks better
List<? extends List<? ObservationInteger>> list = new ArrayList<List<ObservationInteger>>(); - OK

It means any Class implementing List Interface with instances of any Class implementing List Interface with instances of any classes extending "ObservationInteger"

It is a List of Objects, which are all instances of a class that extends List.Because those objects are instances of Lists, each of them happens to contain a certain amount of Objects, which are all instances of a class that extends ObservationInteger.

It's a list of lists of things. Visualize it as a two-dimensional structure (rows & columns).
The ? extends means it is also valid for any subtypes of List and any subtypes of ObservationInteger.

Related

How may I add `MyClass` to `List<? extends MyClass>` [duplicate]

This question already has answers here:
What is PECS (Producer Extends Consumer Super)?
(16 answers)
Method in the type Map<String,capture#1-of ? extends Object> is not applicable
(1 answer)
Closed 4 years ago.
I have a Java Class that contains subitems of Objects that extend MyClass.
class MyClass {
List<? extends MyClass> items;
[...]
For some reason I can't insert MyClass items to this list. I don't Understand why, and how I may bypass this issue. For example:
void foo(){
items = new LinkedList<MyClass>(); // This is OK
items.add(new MyClass()); // Not allowed... why?
}
The compiler says "The method add(capture#1-of ? extends MyClass) in the type List is not applicable for the arguments (MyClass)"
I really don't understand how to bypass this issue, and why the compiler should accept only a type which necessarely extends MyClass.
Note: why am I in the need to use this approach? Because I need to allow extension of MyClass to have list of subitems.
List<? extends MyClass> items means the type parameter is unknown type which is assignable to MyClass.
For example, it could be a List of MySubClass:
public MySubClass extends MyClass{}
List<? extends MyClass> items = new ArrayList<MySubClass>();
Now consider you have MyAnotherSubClass which extends from MyClass too:
public MyAnotherSubClass extends MyClass{}
MyClass item = new MyAnotherSubClass(); // refer it using MyClass
Obviously, List<MySubClass> should not be allowed to contain MyAnotherSubClass:
items.add(item); // compile error
The declaration
List<? extends MyClass> items;
says that items is a List whose type parameter is not exactly known, but is either MyClass or a subclass.
Re-read that, carefully. It explains why it is not type-safe to add anything to such a List: its type parameter is unknown. If it happens to be MySubClass1, then adding a MyClass or a MySubClass2 is incorrect. If it happens to be MySubClass2, then adding a MySubClass1 is incorrect. There is no type at all that can safely be added.
If you want a List to which you can add objects of type MyClass and also objects of any subclass of MyClass, then you probably are looking simply for List<MyClass>.
Technically, a List<? super MyClass> would also serve that specific purpose, but you would have the opposite problem with that: it would not be type safe to assume the list elements to be any type more specific than Object.
Using extends you can only get from the collection. You cannot put into it. You can do that using super.
So, in your case, if you use - List<? super MyClass> items; you will not get any compilation/runtime error.
Though super allows to both get and put, the return type during getting is ? super T.

What's the difference between these generic declarations?

How would you describe – in plain english – the difference between the contents of these lists?
I'm looking for a simple comparison that can be used as a reference.
/* 1 */ List< List< Dog>>
/* 2 */ List< List<? extends Dog>>
/* 3 */ List<? extends List< Dog>>
/* 4 */ List<? extends List<? extends Dog>>
The generic declarations with super are similar. So what about these:
/* 5 */ List<? super List<? extends Dog>>
/* 6 */ List<? extends List<? super Dog>>
Related questions & resources
Explanation of the get-put principle
Generics : List<? extends Animal> is same as List<Animal>?
http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
http://docs.oracle.com/javase/tutorial/java/generics/
A List whose elements are lists of dogs
A List whose elements are lists of a type that extends Dog
A List whose elements are a single subtype of a list of dogs
A List whose elements are a single subtype of a (list of a type that extends Dog)
A List whose elements are a single supertype of a (list of a type that extends Dog)
A List whose elements are a single subtype of a (list of a type that super Dog)
Where "subtype", "supertype", "super", and "extends" are the "generic" versions (i.e. also includes the bounding type)
Examples with Number and subtypes, because why not. Replace Dog with Number.
List<List<Number>> might look like a 2D array of Number elements. Pretty simple.
List<List<? extends Number>> might look like a 2D array, where each row is a different subtype of number. For example, the first row might be a List<Integer>, the second row might be a List<Double>, etc.
List<? extends List<Number>> might be a List<ArrayList<Number>>, List<List<Number>>, List<LinkedList<Number>>, etc. The Number has to stay, because generics are invariant, but you can have List or any of its subtypes as the "overall" type of the elements. You can only pick one of List or its subtypes though, and the one you pick you have to stay with.
List<? extends List<? extends Number>> is similar to List<? extends List<Number>>, except now you can pick Number or any of its subclasses as the elements of the "overall" 2D array. So you can have List<List<Integer>>, List<ArrayList<Integer>>, List<LinkedList<Double>>, etc. As before, you can only pick one of List's subtypes and one of Number's subtypes.
(tricky!) List<? super List<? extends Number>> appears to be equivalent to List<List<? extends Number>>, List<Collection<? extends Number>>, etc. but not List<List<Number>> or anything concrete where a subtype of Number is used. I think this is because List<Number> isn't considered a supertype of List<? extends Number>, which I suppose makes sense due to generics being invariant. List<Object> as well as raw types (List<List>, List<Collection>, etc.) also works.
Same thing as 4, except you get either List<Number> or List<Object> (and apparently List<Serializable>) as the inner list.
As #MadProgrammer said, due to PECS (Producer-Extends-Consumer-Super), any time you have a ? extends for your generic type you won't be able to update the list, only retrieve items from it. So no add()-ing and no set()-ing.
The first one is concrete: it's a List of Lists of Dog, and nothing else.
The second one is abstract on the innermost declaration: it's a List of Lists of some class that inherits from Dog -- say Poodle. It might be a List<ArrayList<Poodle>>.
The third one is abstract on the inner list declaration: its a List of some sort of container that inherits from List -- maybe ArrayList -- of Dog. Then you might have List<ArrayList<Dog>>.
The fourth one is abstract on both: its a List of some kind of container derived from List, filled with some animal that inherits from Dog -- maybe List<ArrayList<Poodle>>.
Replace each "<" by "of".
Whenever there is a "? extends X", insert "or one of its subclasses" after X.

If you're trying to have list with various child classes of a single parent class, how would you do it?

Should you use
List<ParentClass> foo = new ArrayList<ParentClass>
foo.add(ChildClassObject)
or
List<? extends ParentClass> bar - new ArrayList<ParentClass>
bar.add(ChildClassObject)
Also, could someone explain more to me the latter parameterization of List?
Use the first approach. The second doesn't allow you to add any element. This is because the second approach uses an unknown type that extends ParentClass and cannot assure that the elements to be stored are from this type.
More info:
Java Generic with ArrayList <? extends A> add element
List<? extends ParentClass> is a list of some specific subtype of ParentClass. Since, it's not know what exact specific subtype it is, the compiler won't let you add any object to it.
For starters, it's easy to mistake it with any subtype of ParentClass and wonder why they can't add the instances of the subtypes.
For instance, suppose you have a following class hierarchy -
class P { }
class A extends P { }
class B extends P { }
Now if you declare a a list as follows -
List<? extends P> l = ...;
it means l is a list of some specific subtype of P, which could be either A or B (or even P itself), but the compiler doesn't know exactly which one. So, you can't add anything to it, because the chance is that you could be adding an instance of B to a list of As creating some heap pollution.
You would declare such a list when you are only interested in reading the elements of list as P's instances.

ArrayList(Collection<? extends E> c)

I know that in order to create an object of ArrayList type I need to:
ArrayList<MyType> l = new ArrayList<MyType>();
I know it because I've seen this in books.
But looking at Java SE API for the ArrayList constructor I see:
ArrayList(Collection<? extends E> c)
I don't understand, how would I ever get an idea to specify the type of objects my new ArrayList object would hold? How would I know from this definition that I have to specify <MyType> during instantiation and variable declaration?
That method is meant to copy an existing collection instance to the new ArrayList not to create on from scratch. The elements of the collection it will accept have an upper bound of type E which will be the type of your new ArrayList then.
In order to find out if you need type parameters in your declaration, you don't look at the constructor, you look at the class definition itself. The arguments of the constructors have nothing to do with the type of the object itself - a constructor can take any kind of arguments, just like any other method. Here's the class definition:
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
The class ArrayList<E> part says that there is a class called ArrayList and it requires one type parameter (which is called E here).
Let's say you have a set of shape classes. The base class is Shape, and the two implementations are Square and Circle. Now, after you've done some specific setup for the list of objects you wanted, you need to add it all together to send it to a rendering function. The code below should make what I'm describing a little more clear:
ArrayList<Square> squares = readSquares();
ArrayList<Circle> circles = readCircles();
ArrayList<Shape> queue= new ArrayList<Shape>(squares);
queue.addAll(circles);
renderShapes(queue);
The ArrayList(Collection<? extends E> c) constructor makes line five possible. With generics, the processor is not smart enough to automatically determine that Square extends Shape by default. You have to tell the compiler that is what you intended. The way you do that is with the wildcard <? extends E>. Now the compiler will make sure that every object added is at least a Shape.
That's always true when you construct an object for a class that takes a generic type. If you scroll up to the top, you'll see Class ArrayList< E >. That's the hint.

java generics - one impl class, multiple views

I have the interface defined as below and is implemented by a single class MatchedAddressImpl.
interface MatchedAddress extends HouseHelpData, StreetHelpData, TownHelpData
public class MatchedAddressDetails implements MatchedAddress
the client should be provided different views (HouseHelpData or StreetHelpData or TownHelpData or MatchedAddress) of the same MatchedAddressImpl. So I have provided the below API for the clients.
public List<MatchedAddress> matchedAddresses()
public List<? extends HouseHelpData> houseHelpData()
public List<? extends StreetHelpData> streetHelpData();
public List<TownHelpData> townHelpData();
the problem is that the client needs to do something like below and I read ineffective java that the return types should not contain wild cards as the client usage looks ugly...I appreciate it if someone can help me improve the API. what I want is to remove the wildcards from the above methods.
List<? extends StreetHelpData> streetHelpDataList = details.streetHelpData();
For most cases, the proper usage is simply List<StreetHelpData>. You would still be able to put objects of type StreetHelpDataImpl, for instance.
Wildcards are, in my opinion, misleading. Basically, for List<? extends StreetHelpData> it would mean: "This list contains elements all of a certain type, which is a sub-type of StreetHelpData."
Wildcard example:
Consider :
class Animal {}
class Lion extends Animal {}
class Tiger extends Animal {}
The list List<? extends Animal> contains either Lions only (List<Lion>), Tigers only (List<Tiger>), or both (List<Animal>). However, the list List<Animal> can contain all sorts of Animals - Lions and/or Tigers - at all times.
(Thanks to Tom Hawtin for his pointers)
Why do you need wildcards in your API to begin with? Get rid of them.
I'm guessing the reason you've done it that way is you've tried to do the following in your implementation:
public List<HouseHelpData> houseHelpData() {
List<MatchedAddressDetails> results = new ArrayList<MatchedAddressDetails>();
... // populate it
return results;
}
and you've got a compiler error. Java Generic Tutorial explains why the above is illegal - basically it's to prevent you from inadvertedly adding HouseHelpData implementation incompatible with MatchedAddressDetails to the list and then trying to access it (from the downcasted list) as MatchedAddressDetails instance. What you CAN do, however, is:
public List<HouseHelpData> houseHelpData() {
List<HouseHelpData> results = new ArrayList<HouseHelpData>();
...
results.add(new MatchedAddressDetails());
...
return results;
}
No wildcards necessary.
If that was not the reason for adding the wildcards to API, perhaps you can clarify your question and explain what was it.

Categories

Resources