Whats the use of saying ? extends SomeObject instead of SomeObject
List<SomeObject> l;
In this you cannot say List<SomeObject> l = new ArrayList<SubClassOfSomeObjectClass>;
(not allowed)
wheres for
List<? extends SomeObject> l;
you can say
List<? extends SomeObject> l = new ArrayList<SubClassOfSomeObject>;
(allowed)
But note that in List<? extends SomeObject> l = new ArrayList<SubClassOfSomeObject>;
you cannot add anything to your list l because ? represents unknown class (Except null of-course).
Update: For your question in the comment What could I possibly do with a list if I cannot add anything to it?
Now consider a case in which you have to write a function to print your list but mind you it must only accept a List having objects which are subclasses of your SomeObject. In this case as I stated above you cannot use
public void printList(List<SubClassOfSomeObjectClass> someList)
So what would you do? You would do something like
public void printList(List<? extends SomeObject> someList) {
for(SomeObject myObj : someList) {
//process read operations on myObj
}
Java - Using ? extends Interface vs Interface only
You can pass a List<Category>
to public void persist(List<? extends IBean> beansList)
, but you cannot pass a List<Category>
to public void persist(List<IBean> beansList)
.
On the other hand, you can pass a List<IBean>
to both methods.
Java generics: why someObject.getClass() doesn't return Class? extends T?
As per the Javadoc of the getClass
method:
The actual result type is
Class<?
where |X| is the erasure
extends |X|>
of the static type of the expression
on whichgetClass
is called. For
example, no cast is required in this
code fragment
Here, the value for |X|
in your code snippet is MyClass
, hence instance.getClass()
is assignable to only Class<? extends MyClass>
or Class<?>
.
The reason for this specific wording is because when you say that for this variable having type T where <T extends MyClass>
, there can be multiple classes which extend MyClass
and hence capable of satisfying the T extends MyClass
criteria. Without runtime information there is no way of knowing which concrete implementation subclass of MyClass
was passed in the method. Hence to provide a generic solution, it returns <? extends MyClass>
since that would hold true for any subclass of MyClass
irrespective of what class instance is passed in.
Method in the type MapString,capture#1-of ? extends Object is not applicable
? extends Object
You are using generic wildcard. You cannot perform add operation as class type is not determinate. You cannot add/put anything(except null).
For more details on using wildcard you can refer oracle docs.
Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Compile time error
Since we don't know what the element type of c stands for, we cannot add objects to it. The add()
method takes arguments of type E
, the element type of the collection. When the actual type parameter is ?
, it stands for some unknown type
. Any parameter we pass to add would have to be a subtype of this unknown type. Since we don't know what type that is, we cannot pass anything in. The sole exception is null, which is a member of every type
.
Java API class having a method with a meaningless type wildcard
Not quite.
A Function<? super T, U>
is not the same as a Function<? super T, ? extends U>
.
For example, I could still get an Optional<CharSequence>
, even if I passed a Function<Object, String>
to the method. If the method was defined as <U> Optional<U> map(Function<? super T, U> mapper)
, then this would not be possible.
That is because generics are invariant: <T>
is not the same as <? extends T>
. That's a design decision implemented in the Java language.
Let's see how Jon Skeet explains what would happen if generics would not be invariant:
class Animal { }
class Dog extends Animal { }
class Cat extends Animal { }
public void ouch() {
List<Dog> dogs = Arrays.asList(new Dog(), new Dog());
List<Animal> animals;
// This would be legal, right? Because a list of dogs is a list of animals.
List<Animal> animals = dogs;
// This would be legal, right? Because a cat could be added to a
// list of animals, because a cat is an animal.
animals.add(new Cat());
// Unfortunately, we have a confused cat.
}
Although I'm not entirely sure what you mean in your comments, I'll try to elaborate.
If you have full control over the Function
you provide, it doesn't matter whether the method's signature is Function<? super T, U>
or Function<? super T, ? extends U>
, you'll just adapt your Function
accordingly. But the authors of the method probably wanted the method to be as flexible as possible, allowing one to provide a Function
with its second parameter to be also a subclass of U
, instead of only U
itself. Actually you widen its lower bound from U
to a certain subtype of U
.
So the function should really read
<U> Optional<? the-most-general-but-fixed-supertype-of U> map(Function<? super T, U> mapper)
but expressing it that way would be awkward.
I would be indeed awkward. In addition, there is a difference between your proposed notation and the actual method signature of map()
, which involve implications of lower bounds and upper bounds.
Read more:
- A picture explaining the principle "Producer Extends Consumer Super"
- What is the use of saying
<? extends SomeObject>
instead of<SomeObject>
? - Upper and lower bounds
How do I parameterize an extended Collection
You need to specify a type for the ArrayList
's type parameter. For generic type parameters, T
is fairly common. Since the compiler doesn't know what a T
is, you need to add a type parameter to MyList
that can have the type passed in. Thus, you get:
public class MyList<T> extends ArrayList<T>
Additionally, you may want to consider implementing List
and delegating to an ArrayList
, rather than inheriting from ArrayList
. "Favor object composition over class inheritance. [Design Patterns pg. 20]"
Difference between ? super T and ? extends T in Java
extends
The wildcard declaration of List<? extends Number> foo3
means that any of these are legal assignments:
List<? extends Number> foo3 = new ArrayList<Number>(); // Number "extends" Number (in this context)
List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>(); // Double extends Number
Reading - Given the above possible assignments, what type of object are you guaranteed to read from
List foo3
:- You can read a
Number
because any of the lists that could be assigned tofoo3
contain aNumber
or a subclass ofNumber
. - You can't read an
Integer
becausefoo3
could be pointing at aList<Double>
. - You can't read a
Double
becausefoo3
could be pointing at aList<Integer>
.
- You can read a
Writing - Given the above possible assignments, what type of object could you add to
List foo3
that would be legal for all the above possibleArrayList
assignments:- You can't add an
Integer
becausefoo3
could be pointing at aList<Double>
. - You can't add a
Double
becausefoo3
could be pointing at aList<Integer>
. - You can't add a
Number
becausefoo3
could be pointing at aList<Integer>
.
- You can't add an
You can't add any object to List<? extends T>
because you can't guarantee what kind of List
it is really pointing to, so you can't guarantee that the object is allowed in that List
. The only "guarantee" is that you can only read from it and you'll get a T
or subclass of T
.
super
Now consider List <? super T>
.
The wildcard declaration of List<? super Integer> foo3
means that any of these are legal assignments:
List<? super Integer> foo3 = new ArrayList<Integer>(); // Integer is a "superclass" of Integer (in this context)
List<? super Integer> foo3 = new ArrayList<Number>(); // Number is a superclass of Integer
List<? super Integer> foo3 = new ArrayList<Object>(); // Object is a superclass of Integer
Reading - Given the above possible assignments, what type of object are you guaranteed to receive when you read from
List foo3
:- You aren't guaranteed an
Integer
becausefoo3
could be pointing at aList<Number>
orList<Object>
. - You aren't guaranteed a
Number
becausefoo3
could be pointing at aList<Object>
. - The only guarantee is that you will get an instance of an
Object
or subclass ofObject
(but you don't know what subclass).
- You aren't guaranteed an
Writing - Given the above possible assignments, what type of object could you add to
List foo3
that would be legal for all the above possibleArrayList
assignments:- You can add an
Integer
because anInteger
is allowed in any of above lists. - You can add an instance of a subclass of
Integer
because an instance of a subclass ofInteger
is allowed in any of the above lists. - You can't add a
Double
becausefoo3
could be pointing at anArrayList<Integer>
. - You can't add a
Number
becausefoo3
could be pointing at anArrayList<Integer>
. - You can't add an
Object
becausefoo3
could be pointing at anArrayList<Integer>
.
- You can add an
PECS
Remember PECS: "Producer Extends, Consumer Super".
"Producer Extends" - If you need a
List
to produceT
values (you want to readT
s from the list), you need to declare it with? extends T
, e.g.List<? extends Integer>
. But you cannot add to this list."Consumer Super" - If you need a
List
to consumeT
values (you want to writeT
s into the list), you need to declare it with? super T
, e.g.List<? super Integer>
. But there are no guarantees what type of object you may read from this list.If you need to both read from and write to a list, you need to declare it exactly with no wildcards, e.g.
List<Integer>
.
Example
Note this example from the Java Generics FAQ. Note how the source list src
(the producing list) uses extends
, and the destination list dest
(the consuming list) uses super
:
public class Collections {
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
for (int i = 0; i < src.size(); i++)
dest.set(i, src.get(i));
}
}
Also see
How can I add to List<? extends Number> data structures?
java generics bounds
List<? extends SomeObject> l
What do you mean by that? Of course it will generate an error.
Take this example :SomeObject
is Fruit
, you have 2 derived classes Apple
and Orange
Your list what will it contain? Apple
s or Orange
s? The compiler cannot tell. So it generates error.
If you replace List<? extends SomeObject> l
with List<SomeObject> l
. Then this will work because Apple
and Orange
are both Fruit
.
Java Generic with ArrayList ? extends A add element
ArrayList<? extends A>
means an ArrayList of some unknown type that extends A
.
That type might not be C
, so you can't add a C
to the ArrayList.
In fact, since you don't know what the ArrayList is supposed to contain, you can't add anything to the ArrayList.
If you want an ArrayList that can hold any class that inherits A
, use a ArrayList<A>
.
Method argument extends class implements interface
Your pattern class has to extend BasicObject
and extend/implement CodeObject
(which is actually an interface). You can do it with multiple classes declared in the wildcard definition of the method signature, like this:
public <T extends BasicObject & CodeObject> void myMethod(Class<T> clazz)
Note that it won't work if you do it any of these ways:
public <T extends BasicObject, CodeObject> void myMethod(Class<T> clazz)
This is technically valid syntax, but
CodeObject
is unused; the method will accept any classes that extendsBasicObject
, no matter whether they extend/implementCodeObject
.public void myMethod(Class<? extends BasicObject & CodeObject> clazz)
public void myMethod(Class<? extends BasicObject, CodeObject> clazz)
These are just wrong syntax according to Java.
Related Topics
Understanding the etc/Gmt Time Zone
How Read Doc or Docx File in Java
Making Spring-Data-Mongodb Multi-Tenant
Deserialize Java 8 Localdatetime with Jacksonmapper
How to Get All Methods of a Class
Maximum Size of a Method in Java
Why Functional Interfaces in Java 8 Have One Abstract Method
When to Use a List Over an Array in Java
Checked VS Unchecked Exceptions in Java
Why Is 09 "Too Large" of an Integer Number
Java.Sql.Sqlexception: No Suitable Driver Found for Jdbc:Mysql://Localhost:3306/Dbname
How to Cause a Child Process to Exit When the Parent Does
String Parsing in Java with Delimiter Tab "\T" Using Split
How to Retrieve a List of Available/Installed Fonts in Android
How to Use Hibernate @Any-Related Annotations