This question already has answers here:
When to use wildcards in Java Generics?
(6 answers)
Closed 8 years ago.
public <? extends Animal> void takeThing(ArrayList<?> list)
public <T extends Animal> void takeThing(ArrayList<T> list)
Why this statement is wrong? I mean why the ? can't be used in the front? But T can. What is the difference?
Possible duplicate "When to use wildcards in Java Generics?"
Here is an answer for this question.But I don't get what this mean.
"if you say void then there is no return type. if you specify then there is a return type. i didn't know that you can specify to have return type or no return type."
Writing <T extends Animal> binds the type name T, so that it can be referred to later in the definition (including in the parameter list).
If you wrote <? extends Animal>, then you did not name the type. Therefore, you cannot refer to it later. You can't refer to it as ? later because that could be ambiguous (what if you had two type parameters?).
Java forbids you from writing public <?> ... because such a declaration is useless (the type parameter is not named so it cannot be used).
public void takeThing(ArrayList<? extends Animal> list)
means "do something with a list of any subclass of Animal".
public <T extends Animal> void takeThing(ArrayList<T> list)
means "do something with a list of some particular subclass (A.K.A. T) of Animal".
If I call list.get() on the first method, all I know about the returned type is that it extends Animal. On the second method, if I had another instance of List<T>, I know that whatever type T is, both lists would accept the same type.
To take it even further, if I say
Animal animal = list.get(0);
I can no longer say
list.add(animal);
even on the very same list, because we don't have a reference to the generic subtype. If however, I declare a List<T> where <T extends Animal>, I can now say
T animal = list.get(0);
list.add(animal);
because we know that list expects elements of type T.
Related
This question already has answers here:
What is PECS (Producer Extends Consumer Super)?
(16 answers)
Closed 5 months ago.
I am confused by whether wildcards <? super Number> refers to a superclass like Object or a subtype like Integer. In "Java OCP 17 Developer Complete Study Guide" by Jeanne Boyarsky and Scott Selikoff, (Chapter 9 Collections and Generics)
Generics allow you to specify wildcards. <?> is an unbounded wildcard
that means any type. <? extends Object> is an upper bound that means
any type that is Object or extends it. <? extends MyInterface> means
any type that implements MyInterface.
<? super Number> is a lower bound that means any type that is Number or a super class. A compiler error results from code that attempts
to add an item in a list with an unbounded or upper-bounded wildcard
A super class as I understand, is a parent of Number.
But then, why cannot one do this?
import java.util.ArrayList;
import java.util.List;
public class Bewildered {
static class A {}
static class B extends A {}
static class C extends B {}
public static void main(String[] args) {
List<? super B> listBs = new ArrayList<>();
listBs.add(new A());
}
}
compile error:
java: incompatible types: Bewildered.A cannot be converted to capture#1 of ? super Bewildered.B
Because you're thinking about what generics means in the wrong way.
List<? super B> does not mean: "A list that contains Bs or anything that is a supertype of B".
Because that would be utterly useless. Object is a supertype of B. All things are objects. So it's a list of absolutely anything, there's absolutely nothing useful about this list.
No, what List<? super B> means: There is a type. A specific type. It's just.. this code doesn't know what it is. We do know that it is either B or some supertype of B. (So, it's B, or A, or Object, we don't know. The caller picked one of these 3 types). This list is constrained; it cannot contain anything that is not this unknown type.
The point is, you can do this:
List<B> bees = new ArrayList<B>();
List<? super B> list = bees; // legal!
list.add(new A()); // um...
B bee = bees.get(0); // oh no!
See how this goes wrong? There's only one list here - bees and list are both just variables that refer to the exacrt same list. So you if you call list.add, you're modifying the one list that both bees and list are pointing at, so you also add it to bees.
So what's the point of <? super B>?
You can call .add(new B()). Because that works for all legal choices. Whatever the caller picked - if they gave you a List<B>, it works. If it's a List<A>, works. List<Object>? Still acceptable.
No other types fit the bill for <? super B>, so we've exhausted the options: They all 'work out'.
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.
This question already has answers here:
What does the question mark in Java generics' type parameter mean? [duplicate]
(6 answers)
Closed 9 years ago.
I'm trying to use the charts4j api and one of the constructors has this:
public static Data newData(List<? extends Number> data)
It looks like some form of generics to me, but I've never seen this notation before and I don't understand it.
This is an upper-bounded wildcard: ? extends Number.
It means that data can be a list of anything that is Number or a subclass, such as List<Number>, List<Integer>, List<Double>, etc.
Generics in Java are not covariant, so a List<Double> is not a List<Number>. Here, a parameter of type List<? extends Number> allows List<Double> as well as List<Number>, but a parameter of type List<Number> does not allow List<Double>.
As for the List part, it could be anything that implements List, such as LinkedList<Integer> or ArrayList<Double>.
public static Data newData(List<? extends Number> data)
This defines a method that receives a collection implementing the List interface (ArrayList, for example), that contains any subclass of the Number class (even the Number class itself).
Indeed, this concept is related to generics and it's called an Upper Bounded Wildcard. Long story short: It allows you to write a method without a specific type restriction, but a hierarchy restriction instead.
Yes it is wildcard in generics. It means the method will accept any List of type of class that extends Number.
Example: List<Integer>, List<Double>
<T extends SomeClass>
is used when the actual parameter can be some class or any sub class of it. So in your case:
public static Data newData(List<? extends Number> data)
your method can accept a list of any class that is of type Number.
To learn more about Java generics refer:
http://docs.oracle.com/javase/tutorial/extra/generics/methods.html
It is a generic type. It means that the data parameter is a List of any class that extends Number. i.e. If you have a custom class:
public class Nomber extends number {
//stuff...
}
it will take a List<Nomber> as a variable.
It means that the data list can only add a object of Number type or SubNumber type as Double, Integer...
The code below makes complete sense to me - its about adding an element of some type which is supertype of type T and type S is definitely such a super type , so why the compiler refuses to add 'element' into the collection ?
class GenericType<S,T extends S>{
void add1(Collection<? super T> col ,S element ){
col.add(element); // error
// The method add(capture#9-of ? super T) in the type
// Collection<capture#9-of ? super T> is not applicable for the arguments (S)
}
}
Thake an example, if A <- B <- C where <- means that is the supertype, then if S = B and T = C you cannot add an instance of S to a collection of T.
A supertype of T may be the supertype or a subtype of another supertype of T (in this case S).
Collection<? super T> does not mean "a collection that can contain T and any superclass of it" - it's actually not possible to formulate that restriction. What it means is "a collection that can only contain instances of some specific class which is a superclass of T" - basically it ensures that you can add a T to the collection.
The method can be called with a Collection<T>, yet you want to add an S to it.
new GenericType<Object,Integer>().add1(new ArrayList<Integer>(), "");
You are trying to put an element of type S into a collection of type T. Generics aren't polymorphic.
You have to take notice of 2 problems here. you are trying to create an Collection of type concreteObject extends Object and are adding an object
So when you have
Car extends Vehicle{}
ElectricCar extends Car{}
you are trying to do
Collection<? extends Car> collection;
collection.add(new Vehicle());
The second problem lies with the non-polymorphism nature of Generics. See this great explanation -> Is List<Dog> a subclass of List<Animal>? Why aren't Java's generics implicitly polymorphic?
This question already has answers here:
Difference between <? super T> and <? extends T> in Java [duplicate]
(14 answers)
Closed 6 years ago.
I'm having trouble understanding the following syntax:
public class SortedList< T extends Comparable< ? super T> > extends LinkedList< T >
I see that class SortedList extends LinkedList. I just don't know what
T extends Comparable< ? super T>
means.
My understanding of it so far is that type T must be a type that implements Comparable...but what is < ? super T >?
super in Generics is the opposite of extends. Instead of saying the comparable's generic type has to be a subclass of T, it is saying it has to be a superclass of T. The distinction is important because extends tells you what you can get out of a class (you get at least this, perhaps a subclass). super tells you what you can put into the class (at most this, perhaps a superclass).
In this specific case, what it is saying is that the type has to implement comparable of itself or its superclass. So consider java.util.Date. It implements Comparable<Date>. But what about java.sql.Date? It implements Comparable<java.util.Date> as well.
Without the super signature, SortedList would not be able accept the type of java.sql.Date, because it doesn't implement a Comparable of itself, but rather of a super class of itself.
It's a lower-bounded wildcard.
JLS 4.5.1 Type Arguments and Wildcards
Wildcards are useful in situations where only partial knowledge about the type parameter is required. [...] An upper bound is signified by the syntax:
? extends B
where B is the upper bound. [...] it is permissible to declare lower bounds on a wildcard, using the syntax:
? super B
where B is a lower bound.
A List<? super Integer>, for example, includes List<Integer>, List<Number>, and List<Object>.
Wildcards are used to make generics more powerful and flexible; bounds are used to maintain type safety.
See also
Java language guide/Generics/More Fun with wildcards
As to how this is useful in <T extends Comparable<? super T>>, it's when you have something like Cat extends Animal implements Comparable<Animal>.
Look at the signature of Collections.sort
public static <T extends Comparable<? super T>> void sort(List<T> list)
Therefore, with a List<Cat> listOfCat, you can now Collections.sort(listOfCat).
Had it been declared as follows:
public static <T extends Comparable<T>> void sort(List<T> list)
then you'd have to have Cat implements Comparable<Cat> to use sort. By using the ? super T bounded wildcard, Collections.sort becomes more flexible.
See also
Effective Java 2nd Edition, Item 28: Use bounded wildcards to increase API flexibility
Also, PECS principle: "producer extends consumer super"
It means that T must implement Comparable<T itself or one of T's superclasses>
The sense is that because SortedList is sorted, it must know how to compare two classes of its generics T parameter. That's why T must implement Comparable<T itself or one of T's superclasses>
It means that the type T must implement Comparable of T or one of its super classes.
For example, if A extends B, if you want to use SortedList<A>, A must implement Comparable<A> or Comparable<B>, or in fact just Comparable.
This allows the list of As to be constructed with any valid comparator.
Consider the following example:
Using a type parameter defined in the class declaration
public class ArrayList extends AbstractList ... {
public boolean add(E o) // You can use the "E" here ONLY because it's already been defined as part of the class
Using a type parameter that was NOT defined in the class declaration
public <T extends Animal> void takeThing(ArrayList<T> list)
// Here we can use <T> because we declared "T" earlier in the method declaration
If the class itself doesn't use a type parameter, you can still specify one for a method, by declaring it in a really unusual (but available) space - before the return type. This method says that T can be "any type of Animal".
NOTE:
public <T extends Animal> void takeThing(ArrayList<T> list)
is NOT same as
public void takeThing(ArrayList<Animal> list)
Both are legal, but they are different. The first one indicates that you can pass in a ArrayList object instantiated as Animal or any Animal subtype like ArrayList, ArrayList or ArrayList. But, you can only pass ArrayList in the second, and NOT any of the subtypes.