Assigning Java Generic Classes

I have the following classes:

public interface ModelObject { } public interface Resource { } public interface Transformer <F,T>{ } public interface WrapperFactory { Transformer<Resource, Wrap<? extends ModelObject>> createMapper(); } public class Wrap<E extends ModelObject> { } public class AbstractBaseTransformer<F,T> implements Transformer<F,T> { } public class ConcreteModel implements ModelObject { } public class ConcreteTransformer extends AbstractBaseTransformer<Resource, Wrap<ConcreteModel>> { } public class ConcreteFactory implements WrapperFactory { @Override public Transformer<Resource, Wrap<? extends ModelObject>> createMapper() { return new ConcreteTransformer(); } } 

ConcreteFactory does not compile, stating that ConcreteTransformer is incompatible with the returned

 Transformer<Resource, Wrap<? extends ModelObject>> 

I do not see what is wrong here. ConcreteTransformer binds the 1st parameter to the resource (as expected), binding the second parameter to:

 Wrap<ConcreteModel> 

which should contact:

 Wrap<? extends ModelObject> 

since ConcreteModel implements it.

+4
source share
3 answers

Here is a simpler version to narrow down the problem:

 interface ModelObject {} class ConcreteModel implements ModelObject {} class Wrap<E extends ModelObject> {} class SomeGeneric<T> {} class Simple { public SomeGeneric<Wrap<? extends ModelObject>> m() { return new SomeGeneric<Wrap<ConcreteModel>>(); } } 

not compiled.

Your problem is that SomeGeneric<Wrap<ConcreteModel>> not SomeGeneric<Wrap<? extends ModelObject>> SomeGeneric<Wrap<? extends ModelObject>> .

+4
source

Wrap<ConcreteModel> is a subtype of Wrap<? extends ModelObject> Wrap<? extends ModelObject> ? Yes.

Transformer<Resource, Wrap<ConcreteModel>> is a subtype of Transformer<Resource, Wrap<? extends ModelObject>> Transformer<Resource, Wrap<? extends ModelObject>> ? Not.

This is the same as:

Is String a subtype of Object ? Yes.

List<String> is a subtype of List<Object> ? Not.

In principle, for parameterized types that must be compatible, if the top-level parameter is not a wildcard, then the parameters must match exactly. In your case, the top-level parameter is not a wildcard, and the parameters do not match exactly.

Instead, you wanted to

Transformer<Resource, ? extends Wrap<? extends ModelObject>>

+1
source

A Wrap<ConcreteModel> can be assigned to a variable of type Wrap<? extends ModelObject> Wrap<? extends ModelObject> . But the matter is more complicated.

Suppose you have an ArrayList<Wrap<? extends ModelObject>> list ArrayList<Wrap<? extends ModelObject>> list . If you have this type, this means that you can add Wrap<ConcreteModel> to the list, but it also means that you can add Wrap<ModelObject> . In short, this means that you have a list that can contain a Wrap of everything that can be added to ModelObject .

On the other hand, having an ArrayList<Wrap<ConcreteModel>> list means that you can add a Wrap<ConcreteModel> , and a Wrap<ModelObject> cannot be added to it, because the list can only contain wrapped ConcreteModel s, but a wrapped one ModelObject not a wrapped ConcreteModel and cannot be distinguished from it.

This is exactly your case. You announced that your createMapper() method returns Transformer<Resource, Wrap<? extends ModelObject>> Transformer<Resource, Wrap<? extends ModelObject>> . This means that the second argument of the returned transformer must be any subclass of ModelObject , including ModelObject . On the contrary, you are trying to return Transformer<Resource, Wrap<ConcreteModel>> .

The compiler must enforce this because Transformer<F, T> can declare a method:

 void myMethod(F fObject, T tObject); 

If so, the myMethod method of myMethod object of type Transformer<Resource, Wrap<? extends ModelObject>> Transformer<Resource, Wrap<? extends ModelObject>> will accept an object of type ModelObject as the second argument. On the other hand, the same method in an object of type Transformer<Resource, Wrap<ConcreteModel>> cannot accept ModelObject as the second argument.

0
source

Source: https://habr.com/ru/post/1497507/


All Articles