How to call a generic group type method in Java?

I found that I can’t name the common methods of wildcard types and don’t understand why?

public class GenericsTry2 { public static class Element { private Container<? extends Element> container; public Container<? extends Element> getContainer() { return container; } public void setContainer(Container<? extends Element> container) { this.container = container; } public void doStuff() { getContainer().doStuff(this); // how to call this? } } public static class SomeSubElement extends Element { } public static class SomeSubElement2 extends Element { } public static class Container<E extends Element> { public void doStuff(E element) { } } public static void main(String[] args) { Container<SomeSubElement2> c = new Container<SomeSubElement2>(); Element e = new SomeSubElement(); c.doStuff((SomeSubElement2) e); // still can do this at compile time this way } } 
+4
source share
3 answers

Having Container<? extends Element> Container<? extends Element> means that the Container can < express Element (s), but cannot consume Element (s) .

The reason for this is what ? extends Element ? extends Element stands for a whole family of unknown Element subtypes. Suppose you set your container to Container<SomeSubElement> . Then passing this to the container (even you know that Element or a subtype of Element ) will be wrong, because this may or may not be SomeSubElement (depending on the type of Runtime).

In the Generics world, this is called co-dispersion.

To compile the code (I cannot guarantee that you need exactly this), you can do (note that I changed the container to be a consumer of Element (s) instead of the manufacturer)

 public class Element { private Container<? super Element> container; public Container<? super Element> getContainer() { return container; } public void setContainer(Container<? super Element> container) { this.container = container; } public void doStuff() { getContainer().doStuff(this); } } 

However, if you need your Container be a producer and a consumer at the same time, just get rid of the template and parameterize it only with <Element> .

+9
source

Container<E extends Element> means that it contains something E that extends from Element . Not necessarily Element itself.

Imagine what happens if you have:

 Container<RedElement> redElements = new Container<RedElement>(); Container<E extends Element> container = redElements; // According to your logic it will work container.add(new Element()); // Problem here. You just put Element there which is not RedElement. RedElement element = container.getFirst(); 
+1
source

The getContainer() method guarantees the return of some class object that extends the element. Therefore, the compiler at this moment does not know that the return value is really of type Container . If you want to call the doStuff() method of the Container class, you must explicitly specify the result of getContainer() on the type Container .

 ((Container) getContainer()).doStuff(this); 
0
source

All Articles