Implementing bounded generic with java - java

I have an interface
public interface TransferObjectUtil<B extends BusinessObject,T> {
public T to(B domain);
public B from(T transferObject);
}
I am implementing the class for this as
public class ReflectionBasedTransferObjectUtil<B extends BusinessObject, T> implements
**TransferObjectUtil<B extends BusinessObject, T>** {
For the portion within the ** in the above line the compiler complains that for B extends BusinessObject is not allowed. Why would it be so ?
I am just starting with generics, so pardon me for my novice question.

Your location for the generics is a bit wrong / overeager, try it like this
public class ReflectionBasedTransferObjectUtil<B extends BusinessObject, T> implements TransferObjectUtil<B, T> {

Related

Java two-way parameterized class

Is it possible to do this in java without problems?
My IDE highlights my code as "Raw use of parameterized class 'Etat' " and "Unchecked call to 'add(E)' as a member of raw type 'java.util.ArrayList'"
My code :
public abstract class Etat<T extends Transition> {}
public abstract class Transition<E extends Etat> {}
Might you be looking for:
class Etat<E extends Etat<E, T>, T extends Transition<E, T>> {}
class Transition<E extends Etat<E, T>, T extends Transition<E, T>> {}
Then, you can do:
class MonEtat extends Etat<MonEtat, MaTransition> {}
class MaTransition extends Transition<MonEtat, MaTransition> {}
allowing the two types to know each other through their type parameter. For instance, if you declare:
class Etat<E extends Etat<E, T>, T extends Transition<E, T>> {
abstract E apply(T transition);
}
You can then be assured that
MonEtat e = ...;
e = e.apply(new MaTransition()); // compiles, and knows that MonEtat is returned

Incompatible types when using upper bounding wildcard

I'm really confused of how upper bounded types work in Java generics.
Let's say I have
interface IModel<T>
interface I
class A implements I
class B implements I
class C implements I
then I have a method with parameter as follows
foo(IModel<Map<? extends I, Map<? extends I, List<? extends I>>>> dataModel)
calling that method like
IModel<Map<A, Map<B, List<C>>>> model = ...
foo(model)
ends with compilation error
Error:(112, 49) java: incompatible types: IModel<java.util.Map<A,java.util.Map<B,java.util.List<C>>>> cannot be converted to IModel<java.util.Map<? extends I,java.util.Map<? extends I,java.util.List<? extends I>>>>
I have read docs about Java generics from the Oracle web, trying to google it, but there must be something I totally misunderstood.
This question can be shorted as why
foo(IModel<List<? extends I>> dataModel)
can not accept argument like
IModel<List<A>> model
Explanation
List<A> is a subtype of List<? extends I>, so it is ok:
public void bar(List<? extends I> list);
List<A> listA;
bar(listA);
But, it does not make IModel<List<A>> a subtype of IModel<List<? extends I>>, just like IModel<Dog> is not a subtype of IModel<Animal>, so the code you posted can not be compiled.
Solution
You can change it to:
foo(IModel<? extends Map<? extends I, ? extends Map<? extends I, ? extends List<? extends I>>>> dataModel)
or
<FIRST extends I, SECOND extends I, THIRD extends I> void foo(IModel<Map<FIRST, Map<SECOND, List<THIRD>>>> dataModel)
to make it compile.
First of all, I wonder how much effort it would have been for you (one person) to sort out the code to be in this form:
import java.util.List;
import java.util.Map;
interface IModel<T> {}
interface I {}
class A implements I {}
class B implements I {}
class C implements I {}
public class UpperBounds
{
public static void main(String[] args)
{
IModel<Map<A, Map<B, List<C>>>> model = null;
foo(model);
}
static void foo(IModel<Map<? extends I, Map<? extends I, List<? extends I>>>> dataModel)
{
}
}
instead of letting hundreds of people (who want to help you) do this on their own, in order to have something that they can compile and have a look at in their IDE. I mean, it's not that hard.
That being said: Technically, you're missing a few more extends clauses here. This compiles fine:
import java.util.List;
import java.util.Map;
interface IModel<T> {}
interface I {}
class A implements I {}
class B implements I {}
class C implements I {}
public class UpperBounds
{
public static void main(String[] args)
{
IModel<Map<A, Map<B, List<C>>>> model = null;
foo(model);
}
static void foo(IModel<? extends Map<? extends I, ? extends Map<? extends I, ? extends List<? extends I>>>> dataModel)
{
}
}
But you should
not
implement it like that. That's obscure. Whatever this dataModel parameter is, you should consider creating a proper data structure for that, instead of passing along such a mess of deeply nested generic maps.
The reason of why the original version did not compile was already mentioned in other answers. And it can be made clearer by showing an example using a much simpler method call. Consider this example:
interface IModel<T> {}
interface I {}
class A implements I {}
class B implements I {}
class C implements I {}
public class UpperBounds
{
public static void main(String[] args)
{
List<List<A>> lists = null;
exampleA(lists); // Error
exampleB(lists); // Works!
}
static void exampleA(List<List<? extends I>> lists)
{
}
static void exampleB(List<? extends List<? extends I>> lists)
{
}
}
The exampleA method cannot accept the given list, whereas the exampleB method can accept it.
The details are explained nicely in Which super-subtype relationships exist among instantiations of generic types? of the generics FAQ by Angelika Langer.
Intuitively, the key point is that the type List<A> is a subtype of List<? extends I>. But letting the method accept only a List<List<? extends I>> does not allow you to pass in a list whose elements are subtypes of List<? extends I>. In order to accept subtypes, you have to use ? extends.
(This could even be simplified further: When a method accepts a List<Number>, then you cannot pass in a List<Integer>. But this would not make the point of List<A> being a subtype of List<? extends I> clear here)
Having a method method1(Map<I> aMap>) and A being a class implementing I doesn't allow you to call the method with a Map<A> and that's for a reason.
Having the method:
public static void foo2(IModel<I> dataModel) {
System.out.println("Fooing 2");
}
Imagine this code:
IModel<A> simpleModel = new IModel<A>() {};
foo2(simpleModel);
This shouldn't work because you supply a more specific type to a method that requires a generic type. Now imagine foo2 does the following:
public static void foo2(IModel<I> dataModel) {
dataModel = new IModel<B>() {};
System.out.println("Fooing 2 after we change the instance");
}
Here you will try to set IModel to IModel which is valid - because B extends I, but if you were able to call that method with IModel it wouldn't work
Create your model like:
IModel<Map<I, Map<I, List<I>>>> model = ...
and in the corresponding maps and lists add objects of type A, B and C which will be valid and then call the function foo(model)

Correctly extend interface with generics

I would like to correctly extend an interface but since is uses generics, I became a bit confused.
Here is the first interface
public interface A<T extends Resource>{
...
}
I would like to write something like this but it does not work.
public interface B<T extends Resource> extends A<T extends Resource>
{
...
}
I do not understand why this does not work.
Could you explain?
Since you have already defined the type T, it should be:
public interface B<T extends Resource> extends A<T> {
}

Generics and type inference for a generic factory

Sorry in advance for any bad english language in this question.
I have in mind to create a sort of factory which can only create instances of classes defined in a list implemented by a concrete factory instance class. First, i defined this interface :
public interface ValuesSystem {
public interface AllowedValue<T extends Class<? extends SystemValue>>{};
AllowedValue<Class<? extends SystemValue>> getAllowedValue(Enum<?> id);
Map<? extends Enum<?>, AllowedValue<Class<? extends SystemValue>>> getAllowedValues();
<T extends SystemValue> T create(AllowedValue<Class<T>> allowedClass, ValueData data) throws InvalidValueException;
}
The interface AllowedValue is just a "marker wrapper" interface using generics to define a Class instance "allowed" to be create by my factory.
The getAllowedValue is a method used to get a wrapped allowed Class instance from my allowed Class "list" using an internal enumeration from a concrete class implementing this interface (example of a concrete class will come).
The create method is intended to finally create an instance of my allowed Class instance given in the allowedClass argument.
Here is an example of a concrete class implementing this interface :
public class BasicValueSystem implements ValuesSystem {
public BasicValueSystem() {
super();
allowedValues = (Map<VALUES_ID, AllowedValue<Class<? extends SystemValue>>>) getAllowedValues();
}
public static enum VALUES_ID {
MODIFIER
}
private static Map<VALUES_ID, AllowedValue<Class<? extends SystemValue>>> allowedValues;
private class BasicAllowedValue<T extends Class<? extends SystemValue>>
implements AllowedValue<Class<? extends SystemValue>> {
}
#Override
public <T extends SystemValue> T create(
AllowedValue<Class<T>> allowedClass, ValueData data)
throws InvalidValueException {
if (!(allowedClass instanceof BasicAllowedValue)) {
throw new InvalidValueException();
}
return null;
}
#Override
public AllowedValue<Class<? extends SystemValue>> getAllowedValue(Enum<?> id) {
return allowedValues.get(id);
}
#Override
public Map<? extends Enum<?>, AllowedValue<Class<? extends SystemValue>>> getAllowedValues() {
Map<VALUES_ID, AllowedValue<Class<? extends SystemValue>>> allowed = new EnumMap<VALUES_ID, AllowedValue<Class<? extends SystemValue>>>(VALUES_ID.class);
allowed.put(VALUES_ID.MODIFIER, new BasicAllowedValue<Class<ModifierValue>>());
return allowed;
}
}
For the moment the create method return null, but the problem is elsewhere and this not the point of my question
The problem occurs when I tried to create an instance of one of my "allowed" values instance with the following code :
BasicValueSystem bvs = new BasicValueSystem();
AllowedValue<Class<? extends SystemValue>> allowed = bvs
.getAllowedValue(BasicValueSystem.VALUES_ID.MODIFIER);
bvs.create(allowed, new ModifierValueData());
The compiler tells me :
The method create(ValuesSystem.AllowedValue<Class<T>>, ValueData) in the type BasicValueSystem is not applicable for the arguments (ValuesSystem.AllowedValue<Class<? extends SystemValue>>, ModifierValueData)
I think i missed something concerning the type inference made by generics in general.
Can anyone can explain me the create method signature is not applicable in this case and how to fix it ?
Thanks in advance for taking your time.
Note that public interface AllowedValue<T extends Class<? extends SystemValue>> does not make much sense. The only valid type for T would be Class<? extends SystemValue> as the class Class is final and can’t have subclasses. So you can replace it with interface AllowedValue<Class<? extends SystemValue>> without any change in the semantic, but what you really mean (imho) is interface AllowedValue<T extends SystemValue>. Don’t mess around with Class in a type signature. The interface still might have methods referring to Class<T> then.
public interface ValuesSystem {
public interface AllowedValue<T extends SystemValue>{};
AllowedValue<? extends SystemValue> getAllowedValue(Enum<?> id);
public <T extends SystemValue> T create
(AllowedValue<T> allowedClass, ValueData data);
}
Adapt the implementation accordingly, BasicAllowedValue becomes
private class BasicAllowedValue<T extends SystemValue> implements AllowedValue<T>
Then your problem with the using code disappears.
BasicValueSystem bvs = new BasicValueSystem();
AllowedValue<? extends SystemValue> allowed = bvs
.getAllowedValue(BasicValueSystem.VALUES_ID.MODIFIER);
bvs.create(allowed, new ModifierValueData());
will compile.
Note that if AllowedValue shall remain a marker interface without methods only, it is unnecessary, Class<T> already fulfills this role. It will also work when doing it like this:
public interface ValuesSystem {
Class<? extends SystemValue> getAllowedValue(Enum<?> id);
public <T extends SystemValue> T create(Class<T> allowedClass, ValueData data);
}
and
BasicValueSystem bvs = new BasicValueSystem();
Class<? extends SystemValue> allowed = bvs
.getAllowedValue(BasicValueSystem.VALUES_ID.MODIFIER);
bvs.create(allowed, new ModifierValueData());

Usage of extends in Class, Abstract, Interface combination

My main question revolves around when to use and what is the difference between the following when combined with Class, Abstract, Interface:
<E>
<E extends Interface>
<? extends Interface>
Shown below is a detailed question with some code signatures:
This code uses Guava Forwarding Decorators to define specific collections.
Base Interface:
public interface AnimalSetInterface<E extends AnimalI> extends Set<E>
This works:
public interface AsiaI<E extends AnimalI> extends AnimalSetInterface<E>
The following gives an error:
public interface AsiaI<E> extends AnimalSetInterface<E>
Bound mismatch: The type E is not a valid substitute for the bounded
parameter of the type AnimalSetInterface
What I am trying to understand is if I have specified at the Base Interface that I only want <E extends AnimalI> then why do I have to specify again in AsiaI?
I am trying to understand generics and at the same time minimize code.
Also if both classes have such code is there a good way to combine/minimize (remove/generify boilerplate code) it:
Asia:
public Asia(final ImmutableSet<E> animalSet){
super(animalSet);
}
public static <E extends AnimalI> AsiaI<E> of(final ImmutableSet<E> animalSet){
return new Asia(animalSet);
}
Africa:
public Africa(final ImmutableSet<E> animalSet){
super(animalSet);
}
public static <E extends AnimalI> AfricaI<E> of(final ImmutableSet<E> animalSet){
return new Africa(animalSet);
}
public class Africa<E extends AnimalI> extends AnimalSetAbstract implements AfricaI
public class Asia<E> extends AnimalSetAbstract implements AsiaI
The difference is that in the first case, your generic type must extend AnimalI
In the second case, your generic type could be any class.

Categories

Resources