I am a bit confused on how generic works, specially on when we should be using type T vs wildcard ?.
I have the following:
public interface EntityInfo {}
public class Individual implements EntityInfo {}
public abstract class Base<T extends EntityInfo> {}
public class Imp extends Base<Individual>{}
public abstract class BaseMapper<T extends Base<? extends EntityInfo>>{}
public class ImpMapper extends BaseMapper<Imp>{}
This compiles fine. But if I change BaseMapper: from ? extends EntityInfo to S extends EntityInfo, the compiler will complain:
Unexpected boundType parameter 'Imp' is not within its bound; should extend 'Base<S>'I am unsure how this works, why does wildcard work here and specific type will cause the compilation error?
Could anyone help me understand/explain the above?
The key difference between using a wildcard and a specific type parameter is how Java handles generics during compilation.
When you use the wildcard ?, it represents an unknown type that extends the given bound. It allows any subtype of the given bound to be used, but the specific type information is lost. This is useful when you want to allow a wide range of types without specifying the exact type.
However, when you use a specific type parameter, such as S extends EntityInfo, it signifies that you want to have a concrete type that extends EntityInfo. This allows you to use that type information within the class definition.
In the context of the code you provided:
The code compiles fine when you use ? extends EntityInfo in the
BaseMapper class:
public abstract class BaseMapper<T extends Base<? extends EntityInfo>>{}
This works because the type parameter T extends Base with an unknown
subtype of EntityInfo. So, when you create the ImpMapper class:
public class ImpMapper extends BaseMapper<Imp>{}
Imp is a valid type, as it extends Base<Individual>, and Individual implements EntityInfo.
The code does not compile when you replace the wildcard with a specific type parameter:
public abstract class BaseMapper<T extends Base<S extends EntityInfo>>{}
This is because you are trying to declare a type parameter S within the bounds of another type parameter T. This is not valid syntax in Java. Instead, you should declare the type parameter separately:
public abstract class BaseMapper<S extends EntityInfo, T extends Base<S>>{}
Now, when you try to create the ImpMapper class:
public class ImpMapper extends BaseMapper<Imp>{}
You will still encounter a compilation error because BaseMapper expects two type parameters, but you only provided one (Imp). To fix this, provide both type parameters:
public class ImpMapper extends BaseMapper<Individual, Imp>{}
This will compile successfully since Imp extends Base<Individual>, and Individual implements EntityInfo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With