I prefer not to use the type wildcards because they are too restrictive. Say for instance, check this code sample:
List<? extends Number> listExtendsNumber = new ArrayList<>(Arrays.asList(1, 2, 3));
Number num = new Integer(1);
listExtendsNumber.add(num); // compile error - you can't add stuff
listExtendsNumber.add(1); // compile error - you can't add stuff
Sometimes you really want to be this restrictive. However, what I found is that people who use bound wildcard types, they usually want something else.
In your you need to figure out whether you want to accept any type that extends Intent
and Timmed
, or just one particular type?
As far as I can tell, you have the following options:
1. A Wrapper around Set
You can specify a wrapper that deals with one particular type:
public class TimmedIntentSet<T extends Timmed & Intent> implements Set<T> {
private Set<T> set = new HashSet<>();
// consider defining constructors other than the default
@Override
public int size() {
return set.size();
}
@Override
public boolean isEmpty() {
return set.isEmpty();
}
// ... more delegator methods
}
This can be quite flexible. Say for instance, consider the following types:
public interface Timmed {}
public interface Intent {}
public interface TimmedIntent extends Timmed, Intent {}
public class TimmedIntentClass implements TimmedIntent {}
public class TimmedAndIntent1 implements Timmed, Intent {}
public class TimmedAndIntent2 implements Timmed, Intent {}
If you're happy with some type-check warnings, then you can do almost anything with this TimmedIntentSet
:
TimmedIntentSet tis = new TimmedIntentSet<>(); // warning
tis.add(new TimmedAndIntent1()); // warning
tis.add(new TimmedAndIntent2()); // warning
tis.add(new TimmedIntentClass()); // warning
tis.add(2); // compile error
However, if you don't want to @Suppress
your warnings, then you'll see more than a handful of restrictions:
TimmedIntentSet<TimmedIntentClass> tis = new TimmedIntentSet<>();
tis.add(new TimmedAndIntent1()); // compile error
tis.add(new TimmedAndIntent2()); // compile error
tis.add(new TimmedIntentClass()); // cool
tis.add(2); // compile error
2. Add that Set
to the class where it's used
You can add a Set into the class you've just specified above. This accepts one particular type:
class RescheduableRunnableIntent<T extends Intent & Timmed> implements Runnable{
IntentManager intentManager;
T intent;
Set<T> intentMap;
}
You can define a new type that's both Timmed
and Intent
, but that has other kind of restrictions. Using the same types as above, you can't just add any of the Timmed
and Intent
-s to your set:
Set<TimmedIntent> set = new HashSet<>();
set.add(new TimmedAndIntent1()); // compile error
set.add(new TimmedAndIntent2()); // compile error
set.add(new TimmedIntentClass()); // only this is fine
Wrapping up:
It all boils down to what you want to do? Almost anything is possible, but each choice comes with trade-offs.