Where can we use ArrayList< ? extends My_Class> - java

Where can we ArrayList<? extends My_Class> because it won't allow you to add any new element if you declare it of this way:
ArrayList<? extends My_Class> obj=new ArrayList<? extends My_Class>();
list.add(new Derived_My_Class()); //this is compilation error

The widely-used acronym for describing these keywords is: PECS: Producer extends - consumer super.
So, if you use "extends" your collection produces elements of the given type. So you can't add to it, you can only take from it.
An example usage would be to provide a client of your API with a list:
public List<? extends CharSequence> getFoo() {
List<String> list = new ArrayList<String>();
list.add("foo");
return list;
}
Related: Java generics: Collections.max() signature and Comparator

You are correct, your ArrayList cannot be used the way it is derived: there is nothing that you can put into it.
What you want for storing My_Class and its subclasses is simply ArrayList<My_Class>; it will take objects of My_Class and all its DerivedClass correctly.

Well...There is no point one will declare ArrayList like this, rather your intentions will be fullfilled by writing
ArrayList< Supertype> obj=new ArrayList< Supertype>();
As per my epxerience, I have seen this notion in method arguments, where you expect your caller to provide a collection of subtypes of particular Supertype (or return from a method likewise as someone said above). like as follows
public getAnimals(List< ? extends Animal> obj){
obj.add(something); //not allowed
}
there are fair chances that you can add donkeys, monkeys and birds etc in your List of certain type say (Monkey). and get classCastException while getting from it.
That's why It not allowed in this case. read Effective Java by Josh Bloch. he has explained it well with producer consumer analogy(PECS)

Related

Usuage of ? extends anyobject in Java Generics

List<? extends Number> l = new ArrayList<Integer>();
I have the above line of code.
The object 'l' can refer any objects which can be Number any of its sub types.
I know that we can not add anyting to the above list.
Then what is the use of "? extends any_object" since we can not add anything to it ?
In what kind of context it is used ?
Can anyone please explain.
Thanks!!
It’s most useful for method arguments. Consider this:
public void printFormatted(Collection<? extends Number> values) {
NumberFormat format = new DecimalFormat("0.000");
for (Number value : values) {
System.out.println(format.format(value));
}
}
If I declare the method with Collection<Number>, callers must pass a Collection (or List or Set) whose generic type is known to be Number. They cannot pass Collection<Integer>, because Collection<Integer> is not a subclass of Collection<Number> and in fact is not polymorphically compatible with Collection<Number>.
By declaring the method with Collection<? extends Number>, I am saying that callers can pass Collection<Number>, or Collection<Integer>, or Collection<Double>, etc. List<Integer> or Set<Integer> is also acceptable, since the class is polymorphic, even though the generic type is not.
One of possible examples:
When you pass such method as argument, you can iterate over elements of such such list and use methods appropriate to Number class. You need to be aware that you cannot add any elements to such list. You are able to use list.get() method and that way, you're sure that you will get an instanceof Number class.
Such list is then called a producer. If you would need to add elements to list, instead of retrieving them, you would use <? super Number>. That rule is called PECS (Producer Extends Consumer Super).

Java generics: what is the difference between <?> and skipping it?

Maybe it is silly question: Let say I have
abstract class A<T> {
List<Wrapper<T>> doStuff()
}
And I have class B extends A<String> and class C extends A<Integer>
Now I want to have:
List<A> aces = list with instances of B and C;
List<Wrapper> wrapperedItems = flattened list of lists returned from doStuff() on all items in aces
At this point I don't care what type is within Wrapper.
And my question is: shall I use somewhere <?> or can I skip it? What is the difference?
If you use List<Wrapper<?>>, you will be able to get objects out of the list, but you will not be able to add new items. The wildcard essentially correcponds to a type that is different from any other type, including other wildcards.
If you use List<Wrapper>, you will be able to both get list items and add new ones, but the onus is now up to you to guard for improper type casts.

Why generic type is not applicable for argument extends super class for both?

Here is the problem that I have been being tried to find the solution.
We have two class definitions. One of two extends other one.
class T{}
class TT extends T{}
The requirement is that there should be a list keeps object extends T
List<? extends T> list = new ArrayList<>();
But the problem occures when I try to put a TT object ( barely seems it is a subclass of T )
into the list.
list.add(new TT());
Compilation Error Message
The method add(capture#2-of ? extends Cell) in the type List is not applicable for the arguments (Cell)
You can create a List<T> list = new ArrayList<T>(); directly, this can allow all subtypes of T into the list. This is actually little difficult to understand. when you declare it as
List<? extends T> list = ...
It means that it can allow any unknown subtypes of T into the list. But, from that declaration we cannot ensure which is the exact sub-type of T. so, we can only add null into it
List<? extends T> indicates that anything can comes out of it can be cast to T, so the true list could be any of the following:
List<T>
List<T2>
List<TT>
etc
You can see that even a new T cannot safely be added to such a collection because it could be a List<T2> which T cannot be put into. As such, such List cannot have non null entries added to them.
In this case you may simply want List<T>
So why would you ever use this?!
This contravariance can be useful for method parameters or returns, in which a collection will be read, rather than added to. A use for this could be to create a method that accepts any collection that holds items that are T, or extend T.
public static void processList(Collection<? extends Vector3d> list){
for(Vector3d vector:list){
//do something
}
}
This method could accept any collection of objects that extends Vector3d, so ArrayList<MyExtendedVector3d> would be acceptable.
Equally a method could return such a collection. An example of a use case is described in Returning a Collection<ChildType> from a method that specifies that it returns Collection<ParentType>.
The requirement is that there should be a list keeps object extends T
If you just want a List where you can store objects of any class that extend from T, then just create a List like this:
List<T> list = new ArrayList<T>();
The way you've created a list currently, will not allow you to add anything except null to it.
There are boundary rules defined for Java Generics when using WildCards
**extends Wildcard Boundary**
List means a List of objects that are instances of the class T, or subclasses of T (e.g. TT). This means a Read is fine , but insertion would fail as you dont know whether the class is Typed to T
**super Wildcard Boundary**
When you know that the list is typed to either T, or a superclass of T, it is safe to insert instances of T or subclasses of T (e.g.TT ) into the list.
In your example , you should use "super"
An addition to the other answers posted here, I would simply add that I only use wild cards for method parameters and return types. They're intended for method signatures, not implementations. When I put a wildcard into a variable declaration, I always get into trouble.

Generic concept of extends and super

What is the concept behind the Generic extend that why is it not allowed to modify the
list; why does it throw a compile time error when I add a string to list , since String extends Object and should be legal.
If this gives compilation error , then what is the use of that list that is created then.
List<? extends Object> ls=new ArrayList<String>();
ls.add("asd"); // compilation error
And it compiles in the case of super.
List<? super Integer> ls1=new ArrayList<Object>();
ls1.add(1);
I have read Kathy Sierra and Javadoc, but am not able to understand what this means. Please give me a detailed explanation with examples to understand this.
You can't add Strings to a List<? extends Object> because ? could be anything.
If you want to put things into a list, its type parameter should be a superclass of the type you want to put in. (This includes the type itself.)
If you want to get things from a list, its type parameter should be a subclass of the type you want to take out. (This includes the type itself.)
This can be remembered with the acronym PECS - producer-extends, consumer-super.
Compiler does not care try to analize what actual generic type of list is, it checks only ls declared generic type. It is the same as here
void add(List<? extends Object> ls) {
ls.add("1");
...
ls can be eg a list of Integers, you cannot add "1" to it.
Similar explanation applies to super

Java generics confusion

I am a bit of confused about java generics
Here is the code
class Base{}
class Derived extends Base{}
WE can instantiate a list like this
List<? extends Base> list = new ArrayList<Base>();
Why cannot I add a a new item like this
list.add(new Base());
So user cannot use "add" method as far as a wildcard ? in the genetics type?
Thanks
PECS - producer extends, consumer super.
If you replace extends with super, you can add new Base().
List<? extends Base> means "a list that holds instances of any subclass of Base (or Base itself). But it cannot hold instances of two different subclasses.
If you want your list to hold Base and Derived, then use List<Base>. But note that it cannot be later cast to List<Derived>
Just make it
List<Base> list = new ArrayList<Base>();
You shouldn't use wildcards when you know the actual type... just when you're being provided with something with an unknown type.
In such cases, ? extends Base means that the List is only allowed to contain some specific subtype of Base, but you don't know which subtype that is. Because of that, you can't add anything but null to the list.
You can try reading ? as something:
List<? extends Base>
This is "List of something that extends Base". So it is clear that you cannot add a Base (just as you cannot add an Object to a List<String> even when String extends Object.
What you can do in your case is:
List<? super Base>
This is "List of something that is extended by Base". So you can add a Base there (just as you can add a String to a List<Object>, because Object is extended by String.
I think this is a design of Java Generics. The wildcard ? extends Base is compiled to mean that the collection reference can point to a collection object that can hold any ( and all ) types that extend Base.You can write like this as well :
List<? extends Base> _listBaseSubtypes = new ArrayList<Derived>();
Now , with the above line , if you think about it , the below will be obviously an error :
_listBaseSubtypes.add(new Base());
I think Java designers decided to allow the first line of code as valid. In order to avoid the runtime error that the second line of code can cause , it is caught at compile time.
Having said that , the question that comes to mind is : What type of object should be allowed to be added into the collection , given the fact that the actual collection object can be a collection of 'any' derived type ?
Because you can derive as many types as you want , and there cannot be found a single type that is assignment compatible with the type held in the actual collection object ( remember , the collection object could be declared to hold 'any' derived type ) , the simple answer to the question is : None. So , you cannot add any object into the collection through the add interface, because for any object that you may try passing into the add method , there will be complier objection raised on the reason that this type is not compatible with the type that the actual collection object holds.

Categories