Difference between List <? extends interface> and List <interface> [duplicate] - java

This question already has answers here:
When do Java generics require <? extends T> instead of <T> and is there any downside of switching?
(7 answers)
Generics : List<? extends Animal> is same as List<Animal>?
(3 answers)
Closed 5 years ago.
I have this interface:
public interface IModel extends Serializable{
boolean isOnDb();
}
I have an Object that implements the interface IModel :
public class Media implements Serializable, IModel {
#Override
public boolean isOnDb() {
return isOnDb;
}
}
I want to create a List where I can put objects that implement the interface IModel. Something like this:
List<? extends IModel> list= new ArrayList<>();
Media media = new Media();
list.add(m);
the code above doesn't compile. But I have no error if I do :
List<IModel> list= new ArrayList<>();
Media media = new Media();
list.add(m);
What's the difference between List<? extends IModel> and List<IModel>?
Thank you in advance

Related

Generic variable declaration with wildChar vs without wildChar [duplicate]

This question already has answers here:
What does the question mark in Java generics' type parameter mean? [duplicate]
(6 answers)
When to use generic methods and when to use wild-card?
(9 answers)
Closed 3 months ago.
interface Shape { }
class Circle implements Shape { }
class ShapeContainer<T extends Shape> {
T sh;
public ShapeContainer(T newInstance) {
sh = newInstance;
}
...
}
class Main {
public static void main(String[] a) {
ShapeContainer<Shape> A = new ShapeContainer(new Circle());
ShapeContainer<? extends Shape> B = new ShapeContainer(new Circle());
}
}
What are the pros and cons of declaring the variable as ShapeContainer<Shape> A vs ShapeContainer<? extends Shape> B
What condition should each one be preferred?

Java/Generics: Return a list of extending a type? [duplicate]

This question already has answers here:
What is PECS (Producer Extends Consumer Super)?
(16 answers)
Closed 3 years ago.
If I have the following:
class A {}
class B extends A {}
public <T extends A> List<T> getList() {
List<T> list = new ArrayList<>();
list.add(new A());
return list;
}
But I get the error: add(T) in List cannot be applied to A
What I would like to do is return a list of Class A or any class extending Class A. Why doesn't it work here?
You can't add an instance of A to a list of type that extends A, such as List<B>, since A isn't a B (but visa-versa).

Downcast parameter in Child class Java [duplicate]

This question already has answers here:
Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?
(19 answers)
Closed 5 years ago.
public class Contract extends StandardEntity {
/***/
#Composition
#OnDeleteInverse(DeletePolicy.UNLINK)
#OnDelete(DeletePolicy.CASCADE)
#OneToMany(mappedBy = "contract")
protected List<Objective> objectives;
/***/
Is it possible to downgrade argument objectives in child class (ContractWthDeadLines extends Contract) from List< Objective> to List< ObjectiveWitchDeadLine>:
public class ObjectiveWitchDeadLine extends Objective
Make your Contract class generic
public class Contract<T extends Objective> extends StandardEntity {
protected List<T> objectives;
}
and if you extend it you can change the type
public class ContractDeadline extends Contract<ObjectiveWitchDeadLine> {
}

Generic map not compiling with nested structure [duplicate]

This question already has answers here:
Java HashMap nested generics with wildcards
(3 answers)
Closed 6 years ago.
I want to implement a map wrapper that use genericity to enforce a type relation between the key and the value.
The following code does not compile :
Map<Class<? extends Serializable>, List<List<? extends Serializable>>> collection = new HashMap();
private <T extends Serializable> void add(Class<T> type, List<List<T>> item) {
collection.put(type, item);
}
whereas this compile :
Map<Class<? extends Serializable>, List<? extends Serializable>> collection = new HashMap();
private <T extends Serializable> void add(Class<T> type, List<T> item) {
collection.put(type, item);
}
why is there a difference between a 2nd and a 3rd level generic type ?
Generics are invariant, the second type parameter of your map is List<List<? extends Serializable>>, that means that the second argument of put must match this exactly.
i.e. You can only add a List to the map if it has the exact parameter List<? extends Serializable>, and T is not exactly ? extends Serializable.
You can fix this by having another ? extends in your map and method declaration:
Map<Class<? extends Serializable>, List<? extends List<? extends Serializable>>> collection = new HashMap<>();
private <T extends Serializable> void add(Class<T> type, List<? extends List<T>> item) {
collection.put(type, item);
}

Why second example compiles sucessfuly [duplicate]

This question already has answers here:
Difference between <? super T> and <? extends T> in Java [duplicate]
(14 answers)
Closed 6 years ago.
import java.util.*;
class Test
{
public static class Base
{
}
public static class Derived1
extends Base
{
}
public static class Derived2
extends Base
{
}
public static void main (String[] args)
{
//Example1.
List<? extends Base> e = new ArrayList<Base>();
e.add(new Derived1()); //this won't compile
//Example2.
List<? super Base> b = new ArrayList<Base>();
b.add(new Derived1()); //this compiles
}
}
List<? super Base> b can be assigned either a List<Base> or a List<Object>. A Derived1 instance can be added to both, so the b.add(new Derived1()) statement passes compilation.
On the other hand, List<? extends Base> e may be assigned a List<Derived2>, so the compiler doesn't allow to add a Derived1 instance to it.
See What is PECS (Producer Extends Consumer Super)?.
If you are adding something to a List<T>, then the list is a consumer of the thing you are adding. As such, the type of the list elements, T, must be the same as the thing you are trying to add or a supertype.

Categories